bash переименовать файл / добавить целое число в имени файла с различными расширениями в нескольких подкаталогах - PullRequest
0 голосов
/ 24 сентября 2018

Я хочу вставить целое число в имена файлов с различными расширениями в нескольких подкаталогах, используя bash.

Примеры:

  • ./trial2/foo.hhh -> ./trial2/foo1.hhh
  • ./trial2/trial3/foo.txt -> ./trial2/trial3/foo1.txt

Я попытался отделить имя файла от расширения и вставить между ними целое число:

i=123
find . -type f -exec sh -c ' echo mv "$0" "${0%.*}${i}.${0##*.}" ' {} \;
mv ./trial2/foo.hhh ./trial2/foo.hhh

Но вывод переменной ${i} не печатается.Почему?
Если я поменяю на:

find . -type f -exec sh -c ' mv "$0" "${0%.*}123.${0##*.}" ' {} \;
mv ./trial2/foo.hhh ./trial2/foo123.hhh

Номер напечатан.Однако мне нужна переменная ${i}, так как она будет определена в цикле for.

Ответы [ 2 ]

0 голосов
/ 24 сентября 2018

Передайте $i в $0, и ваши имена файлов в $1 и далее, и вы можете изменить значение с -exec ... {} \; на -exec ... {} +, используя, таким образом, только один экземпляр sh для переименования потенциально нескольких файлов.

Следующее требует bash, но генерирует mv команды, которые гарантированно будут правильными даже при наличии злонамеренных или сбивающих с толку имен файлов (с пробелами, символами новой строки, управляющими символами и т. Д.):

find . -type f -exec bash -c '
  logcmd() { printf "%q " "$@"; printf "\n"; }  # a more accurate replacement for echo
  for f; do
    logcmd mv "$f" "${f%.*}${0}.${f##*.}"
  done' "$i" {} +
0 голосов
/ 24 сентября 2018

Редактировать

Вы почти у цели;Вы просто попали в тонкость цитирования.i объявлено в текущей оболочке, поэтому его необходимо каким-то образом передать в sh, запущенный find.В вашей текущей команде ${i} в одинарных кавычках, поэтому не интерпретируется bash до того, как цитируемый материал передан sh.

Как предложил Чарльз Даффи:

find . -type f -exec sh -c ' echo mv "$0" "${0%.*}${1}.${0##*.}" ' {} "$i" \;

В команде sh, как вы знаете, $0 - это {}.$1 является вторым параметром sh, который "$i" (i раскрывается как одно слово).Вместо ${i} команда sh использует ${1} для доступа к этому параметру (копия i).

Оригинал

В этом примере i интерполируетсяв текущей оболочке.

Before: find . -type f -exec sh -c ' echo mv "$0" "${0%.*}${i}.${0##*.}" ' {} \;
After:  find . -type f -exec sh -c ' echo mv "$0" "${0%.*}'"${i}"'.${0##*.}" ' {} \;
                                                          ^^    ^^

'"${i}"' выбрасывает вас из одинарных кавычек, затем расширяет i, а затем возвращает вас в одинарные кавычки.Таким образом, команда, которую вы передаете sh, содержит значение i, которое вы хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...