简体   繁体   English

递归重命名目录中的所有子目录

[英]Rename all subdirectories within a directory recursively

I'm currently using the following code to list all of the subdirectories within a specific directory. 我当前正在使用以下代码列出特定目录中的所有子目录。

$dir = realpath('custom_design_copy/');

$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::SELF_FIRST);

foreach($objects as $name => $object){
    if(is_dir($object)){
        echo "$name<br />";
    }
}

This gives me results that look something like this. 这给了我看起来像这样的结果。

C:\Data\Web\custom_design_copy\Product
C:\Data\Web\custom_design_copy\Product\images
C:\Data\Web\custom_design_copy\Product\Scripts

What I want to do is rename all of these subdirectories with strtoupper() in order to normalize all of their names. 我要执行的操作是使用strtoupper()重命名所有这些子目录,以规范其所有名称。 I'm aware of the rename() function but I fear that if I try the following: 我知道rename()函数,但是我担心如果尝试以下操作:

rename($name, strtoupper($name));

I'll wind up modifying one of custom_design_copy's parent directory names, which is what I hope to avoid. 我最终将修改custom_design_copy的父目录名称之一,这是我希望避免的。 How can I avoid this issue? 如何避免这个问题? I was considering using substr() and searching for the last occurrence of "\\" in order to isolate the directory name at the end, but there has to be an easier solution to this. 我正在考虑使用substr()并搜索最后一次出现的“ \\”,以便在末尾隔离目录名称,但是必须有一个更简单的解决方案。 The end result I'm looking for is this. 我要寻找的最终结果是这个。

C:\Data\Web\custom_design_copy\PRODUCT
C:\Data\Web\custom_design_copy\PRODUCT\IMAGES
C:\Data\Web\custom_design_copy\PRODUCT\SCRIPTS

EDIT: While waiting for advice, I attempted my initial approach and found that it worked. 编辑:在等待建议的同时,我尝试了最初的方法,发现它可行。

$dir = realpath('custom_design_copy/');

$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::SELF_FIRST);

foreach($objects as $name => $object){
    if(is_dir($object)){
        $slashPos = strrpos($name, '\\');
        $newName  = substr($name, 0, $slashPos + 1) . strtoupper(substr($name, $slashPos + 1));

        rename($name, $newName);

        echo "$name<br />";
    }
}

Your example uses the RecursiveIteratorIterator::SELF_FIRST flag, which lists leaves and parents in iteration with parents coming first ( from the docs ). 您的示例使用RecursiveIteratorIterator::SELF_FIRST标志,该标志列出了迭代中的叶子和父对象,其中父对象排在第一位来自docs )。

This means that with a directory structure like: 这意味着具有如下目录结构:

foo/
foo/bar/
foo/bar/bat.txt

The iteration order is from parents towards leaves: 迭代顺序是从父级到叶子:

  1. foo/ 富/
  2. foo/bar/ 富/酒吧/
  3. foo/bat/bat.txt 富/蝙蝠/ bat.txt

This can be problematic, as you have noted already. 正如您已经指出的那样,这可能会有问题。


For your needs, the RecursiveIteratorIterator::CHILD_FIRST flag should be used. 根据您的需要,应使用RecursiveIteratorIterator::CHILD_FIRST标志。 This flag instructs the iterator to go in the other direction, from leaves towards parents. 该标志指示迭代器从叶子到父级朝另一个方向移动。

  1. foo/bar/bat.txt 富/酒吧/ bat.txt
  2. foo/bar/ 富/酒吧/
  3. foo/ 富/

You can store all directories in an array and after that you can loop the array in descending order changing the last folder to uppercase. 您可以将所有目录存储在数组中,然后可以按降序循环数组,将最后一个文件夹更改为大写。

Here is an example: 这是一个例子:

$path = 'custom_design_copy' . DIRECTORY_SEPARATOR;

$main_dir = realpath($path);

$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($main_dir), RecursiveIteratorIterator::SELF_FIRST);

foreach ($objects as $name => $object) {

    if ($object->isDir() && !in_array($object->getFilename(), array('.', '..'))) {

        $directories[] = $name;

    }
}

foreach (array_reverse($directories) as $dir) {
    rename($dir, last_path_upper($dir));
}

function last_path_upper($str) {

    $arr = explode(DIRECTORY_SEPARATOR, $str);

    $last = array_pop($arr);

    return join(DIRECTORY_SEPARATOR, $arr) . DIRECTORY_SEPARATOR . strtoupper($last);

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM