Переименовать все подкаталоги в каталоге рекурсивно

В настоящее время я использую следующий код для перечисления всех подкаталогов в определенном каталоге.

$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 />";
}
}

Это дает мне результаты, которые выглядят примерно так.

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

То, что я хочу сделать, это переименовать все эти подкаталоги с strtoupper() для того, чтобы нормализовать все их имена. Я знаю о rename() функционировать, но я боюсь, что если я попробую следующее:

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

Я закончу модификацию одного из имен родительских каталогов custom_design_copy, чего я надеюсь избежать. Как я могу избежать этой проблемы? Я думал об использовании substr() и поиск последнего вхождения «\», чтобы изолировать имя каталога в конце, но для этого должно быть более простое решение. Конечный результат, который я ищу, таков.

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

РЕДАКТИРОВАТЬ: В ожидании совета, я попытался мой первоначальный подход и обнаружил, что он работает.

$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 />";
}
}

0

Решение

Ваш пример использует RecursiveIteratorIterator::SELF_FIRST флаг, который списки листьев и родителей в итерации с родителями, идущими первыми (из документов).

Это означает, что с такой структурой каталогов:

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

Порядок итерации от родителей к листьям:

  1. Foo /
  2. Foo / бар /
  3. Foo / бита / bat.txt

Это может быть проблематично, как вы уже отметили.


Для ваших нужд RecursiveIteratorIterator::CHILD_FIRST Флаг должен быть использован. Этот флаг указывает итератору идти в другом направлении, от листьев к родителям.

  1. Foo / бар / bat.txt
  2. Foo / бар /
  3. Foo /
1

Другие решения

Вы можете хранить все каталоги в массиве, и после этого вы можете зацикливать массив в порядке убывания, изменяя последнюю папку на верхний регистр.

Вот пример:

$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);

}
0

По вопросам рекламы [email protected]