На сервере Linux у меня есть каталог, полный файлов с цифрами в именах. Некоторые файлы начинаются с двух нулей, например 00305005. Я пишу сценарий оболочки bash, и одним из шагов является переименование всех файлов, начинающихся с 00, так, чтобы они начинались с @ 0. Файл, о котором я упоминал ранее, будет @ 0305005.
Проблема, с которой я столкнулся, заключается в том, что когда я пытаюсь переименовать файлы, я в конечном итоге меняю все экземпляры 00 в имени файла на @ 0 следующим образом: @ 0305 @ 05. Я использовал следующий код и не знаю, как его исправить:
for f in 00*; do mv "$f" "${f//00/@0}"; done
Если вы застряли с магией оболочки, перейдите по другому пути и попробуйте изменить имя файла с помощью другого инструмента, например f.ex. sed
for f in 00*; do
new_f=$( echo "$f" | sed 's/00/@0/' )
echo mv "$f" "$f_new"
done
Я вставил echo
перед mv
так что вы можете сначала проверить, если mv
Посмотрите хорошо, прежде чем испортить свои файлы. Затем вы можете удалить это echo
.
Когда вы используете ${var//pattern/replacement}
, то \\
означает "заменить все случаев. В этом случае вы хотите заменить только первое вхождение, поэтому вы можете использовать только /
. Или вы могли бы быть еще более конкретным и использовать /#
, который заменит только начало строки; это не должно иметь значения, поскольку вы обрабатываете только файлы, начинающиеся с 00
, но я был бы склонен использовать его, чтобы четко обозначить цель. Вот демо:
$ f=00305005
$ echo "${f//00/@0}" # // = replace all
@0305@05
$ echo "${f/00/@0}" # / = replace first one -- this does what you want
@0305005
$ echo "${f/#00/@0}" # /# = replace at beginning -- this also does what you want
@0305005
$ g=90305005 # Let's test with a name that *doesn't* start with 00
$ echo "${g/00/@0}" # / replaces the first match, no matter where it is in the string
90305@05
$ echo "${g/#00/@0}" # /# does not replace if the beginning does not match
90305005
Я также рекомендую использовать mv -i
для любого вида массового перемещения / переименования, чтобы избежать потери данных в случае конфликта имен или ошибок. Итак, вот что я бы порекомендовал:
for f in 00*; do mv -i "$f" "${f/#00/@0}"; done