15

I'm trying to move a folder by renaming it. Both the test1 and test2 folders already exist.

rename(
 "test1",
 "test2/xxx1/xxx2"
);

The error I get is: rename(...): No such file or directory

I assume this is because the directory "xxx1" does not exist. How can I move the test1 directory anyway?

Workoholic
  • 179
  • 1
  • 1
  • 5

4 Answers4

19

You might need to create the directory it is going into, e.g.

$toName = "test2/xxx1/xxx2";

if (!is_dir(dirname($toName))) {
    mkdir(dirname($toName), 0777, true);
}

rename("test1", $toName);

The third parameter to mkdir() is 'recursive', which means you can create nested directories with one call.

Petah
  • 45,477
  • 28
  • 157
  • 213
Tom Haigh
  • 57,217
  • 21
  • 114
  • 142
  • Won't the rename fail if the directory already exists? Both "xxx1" and "xxx2" are directories, and the second parameter might as well be "xxx2/"... – Workoholic Apr 16 '10 at 15:05
  • it will fail if the target `$toName` exists, but wouldn't you have had that problem with your original code anyway? – Tom Haigh Apr 16 '10 at 15:15
2

Why not make sure all parent directories exist first, by making them? mkdir - use the recursive parameter.

Andy Shellam
  • 15,403
  • 1
  • 27
  • 41
2

Your assumption was correct, this is because "xxx1" in your example does not exist.

So, before rename("oldname", "/some/long/nested/path/test2/xxx1/newname") you have to create directory tree structure: /some/long/nested/path/test2/xxx1/ but newname file (or directory) must not exist at the moment of rename function call.

To generalize the solution look at the following naive function:

function renameWithNestedMkdir($oldname , $newname)
{
     $targetDir = dirname($newname); // Returns a parent directory's path (operates naively on the input string, and is not aware of the actual filesystem)

    // here $targetDir is "/some/long/nested/path/test2/xxx1"
    if (!file_exists($targetDir)) {
        mkdir($targetDir, 0777, true); // third parameter "true" allows the creation of nested directories
    }

    return rename($oldname , $newname);
}

// example call
renameWithNestedMkdir("oldname", "/some/long/nested/path/test2/xxx1/newname");

// another example call
renameWithNestedMkdir("test1", "test2/xxx1/xxx2");

I named this implementation "naive" because in real production you should also think about handling some edge cases: what if $newname already exists? What if /some/long/nested/path/test2/xxx1 already exists but it's a file (not a directory)? Why I put 0777 access rights while mkdir? What if mkdir failed?

Petr
  • 7,275
  • 2
  • 16
  • 16
0

I think test2/xxx1 would need to exist, so you'd need to use mkdir before you move it.

Josh
  • 1,261
  • 2
  • 18
  • 34