Вы указываете, что сказали Если
.
ключевые слова bash чувствительны к регистру; вы должны использовать , если
(нижний регистр).
Вы можете использовать переименование Perl, если оно доступно. Под переименованием Perl я подразумеваю переименование prename или файла -, а не rename.ul, который может быть тем, что rename
указывает на вашу систему, и который определенно приведет к ошибке, если вы попытаетесь использовать его с аргументами кода, которые у меня есть. предлагается ниже...
В моей системе (Ubuntu 17.10 -Я установил пакет rename
для переименования Perl):
$ readlink -e $(type -P rename)
/usr/bin/file-rename
Это единственная среда, в которой я тестировал этот ответ!
Если у вас есть только два уровня каталога, как в вашем примере, вы можете запустить из каталога lokesh
что-то вроде этого:
rename -n 's|/|/x_|' */*.c
Всегда запускайте сначала с флагом -n
, который показывает, какое изменение будет предпринято, если вы запустите тот же код без -n
. Если вы видите правильный результат, удалите -n
.
Если у вас сложная структура каталогов, вы можете использовать рекурсивную подстановку, если она доступна. В Баше:
shopt -s globstar
Тогда попробуйтеrename
:
rename -n 's|(.*)/|$1/x_|'./**/*.c
Это фиксирует все до последнего элемента пути (.*)/
и воспроизводит его с обратной ссылкой $1
.
В противном случае (, если вы не можете использовать рекурсивную подстановку ), используйтеfind
:
find. -type f -name "*.c" -exec rename -n 's|(.*)/|$1/x_|' {} +
Хотя это будет медленнее, если файлы находятся во многих каталогах,вы также можете использовать -execdir
, который допускает более простое регулярное выражение (Я обнаружил заметную разницу в скорости между-exec
(менее секунды )и-execdir
(3 -4 секунды )с ~1113 .c
файлов в ~175 каталогах):
find. -type f -name "*.c" -execdir rename -n 's|/|/x_|' {} +
-n
приводит к запутанным -выглядящим результатам с -execdir
, но если базовые имена выглядят правильно, все в порядке.
Однако, благодаря комментарию Кусалананды , я понимаю, что это зависит от наличия GNU find
, где все аргументы -execdir
начинаются с ./
, а не версии OpenBSD, где они не. Если имя файла вообще не имеет префикса пути, я думаю, вы можете использовать эту версию:
find. -type f -name "*.c" -execdir rename -n -- 's|^|x_|' {} +
но я не могу это проверить, так как у меня нет OpenBSD find
.
Тем не менее,Элиа Каган очень помог придумал гораздо лучшее регулярное выражение , которое работает независимо от используемой реализации find
и от того, используете ли вы -exec
или -execdir
, а также работает с рекурсивной подстановкой:
rename -n 's|[^/]+$|x_$&|'
Это соответствует как минимум 1 символу (s ), которые не являются /
в конце($
)пути, а затем воспроизводит все совпадение($&
)после добавленного x_
. Эта команда должна работать везде, find
и переименование Perl доступно:
find. -type f -name "*.c" -exec rename -n 's|[^/]+$|x_$&|' {} +
ПРИМЕЧАНИЕ:При написании ниже я использовал OpenBSD find
, в которой -execdir utility {} ';'
заменит {}
базовым именем найденных файлов. В GNU find
{}
также будет базовым именем найденного файла, но к нему будет дополнительно добавляться ./
, что делает первую команду find
ниже бесполезной. Для пользователей GNUfind
(большинство людей на Linux, например ), прокрутите вниз до других вариантов решения.
Вы хотите найти все .c
файлы в каталоге lokesh
или ниже него и добавить к их именам префикс x_
.
find lokesh -type f -name '*.c' -execdir echo mv {} x_{} ';'
Выражения -type f
и -name '*.c'
найдут все соответствующие файлы, а -execdir mv {} x_{} ';'
переименует найденные файлы.
Выражение -execdir
не является стандартным, но большинство реализаций find
поддерживают его. Он отличается от -exec
тем, что данная утилита выполняется с родительским каталогом найденного пути в качестве рабочего каталога. Поэтому {}
в командной строке будет базовым именем файлов, которые мы хотим переименовать (, а не полным путем, как в случае с-exec
).
Запустите это один раз, а затем удалите echo
, когда увидите, что он работает правильно. echo
предотвратит фактическое переименование файлов mv
.
В системах, которые не поддерживают-execdir
(или не поддерживают -execdir
, как это делает OpenBSD):
find lokesh -type f -name '*.c' \
-exec sh -c 'for name do echo mv "$name" "${name%/*}/x_${name##*/}"; done' sh {} +
или, короче, но чуть менее эффективно,
find lokesh -type f -name '*.c' \
-exec sh -c 'echo mv "$1" "${1%/*}/x_${1##*/}"' sh {} ';'
В обоих этих вариантах используется короткий сценарий оболочки, который в конечном итоге делает одно и то же.:
mv "$name" "${name%/*}/x_${name##*/}"
Это перемещает файл с полным путем в $name
на новое имя с префиксом x_
в том же каталоге. Замена параметра ${name%/*}
эквивалентна $( dirname "$name" )
и дает родительский каталог пути, а ${name##*/}
эквивалентна $( basename "$name" )
, который дает базовому имени (компонент имени файла )имени пути.