У меня есть файлы и каталоги, начинающиеся с"категория-значок-"во многих подкаталогах. Я пытаюсь переименовать их рекурсивно в"категория-значки-". Обратите внимание, что я добавил отсутствующие"г"ккатегорияи"с"в концеиконки.
Я просмотрел множество других вопросов, связанных с переименованием нескольких файлов и каталогов, но ни один из них не подошел мне!
Буду весьма признателен за небольшое пояснение ответа.
ОТРЕДАКТИРОВАНО: Вот пример моей структуры каталогов:
test/cateory-icon-archery/cateory-icon-archery.png
[email protected]
test/cateory-icon-automotive/cateory-icon-automotive.png
[email protected]
решение1
Поскольку вам нужно сделать это рекурсивно, find
это лучший инструмент для использования. Чтобы изменить имя, вы можете использовать sh
в -exec
вызове. Вот пример:
find /some/path -name 'cateory-icon' -exec sh -c 'mv "$1" "${1%/*}/category-icon-${1#cateory-icon-*}"' -- {} \;
Расширение ${1#cateory-icon-*}
получает имя файла после cateory-icon
.
решение2
В zsh введите следующее .zshrc
(или выполните это в командной строке для одноразового выполнения):
autoload zmv
alias zcp='zmv -C'
alias zln='zmv -L'
Thezmv
функцияв сочетании с zshПодстановочные знаки и функции глобализациипозволяет легко переименовывать и копировать файлы. Вот несколько способов сделать то, что вы хотите:
zmv '(**/)cateory-icon-(*)' '${1}category-icons-$2'
zmv -w '**/cateory-icon-*' '${1}category-icons-$2'
zmv '**/cateory-icon-(*)' '$f:h/category-icons-$1'
Объяснение некоторых функций zsh:
**/
рекурсивно сопоставляет файлы в подкаталогах.- Скобки в исходном выражении обозначают группы.
$NUM
или${NUM}
в выражении замены заменяется частью исходного имени, содержащейся в группе NUMth. - Скобки вокруг
**
немного странные: их можно ставить только вокруг**/
, не больше и не меньше. - Параметр автоматически
-w
помещаетzmv
каждый подстановочный знак в группу (для**
, это**/
часть, которая находится в группе, с конечным/
). $f
в замене подразумевается полное имя исходного файла.$VAR:h
означает часть каталога$VAR
. Обычно это$VAR
до последнего/
, но все крайние случаи (foo
,foo/
,/
, …) обрабатываются правильно. Базовое имя доступно как$VAR:t
.
решение3
Использование Perl для максимальной переносимости:
#!/usr/bin/env perl
use strict;
use warnings;
use File::Find;
use File::Copy qw(move);
my $new_name;
finddepth( sub {
if(/cateory-icon/){
($new_name = $File::Find::name) =~ s{.*/\Kcateory-icon}{category-icons};
move $File::Find::name => $new_name;
}
},
'.')
Объяснение
- При этом используются два основных модуля Perl:
File::Find
для рекурсивного обхода деревьев каталогов иFile::Copy
для рекурсивного копирования/перемещения каталогов. - Функция
finddepth
(изFile::Find
) просматривает список каталогов, предоставленный в качестве второго аргумента (.
в данном случае это текущий каталог; при необходимости измените его). - Первый аргумент
finddepth
— это ссылка на подпрограмму, которая выполняется для каждого файла,finddepth
встречающегося при обходе дерева. - Мы начинаем эту подпрограмму с
if
условия: если совпавшее имя файла содержит шаблонcateory-icon
, то мы формируем новое имя, внося необходимые исправления, и используем функциюmove
(изFile::Copy
), чтобы изменить текущее имя на новое.
Отказ от ответственности
Этот код не тестировался. Сначала попробуйте его на фиктивном дереве каталогов!