Скопируйте и переименуйте несколько файлов с регулярными выражениями в bash

У меня есть файловая структура, которая выглядит так:

A/
    2098765.1ext
    2098765.2ext
    2098765.3ext
    2098765.4ext
      12345.1ext
      12345.2ext
      12345.3ext
      12345.4ext

B/
    2056789.1ext
    2056789.2ext
    2056789.3ext
    2056789.4ext
      54321.1ext
      54321.2ext
      54321.3ext
      54321.4ext

Мне нужно переименовать все файлы, начинающиеся с 20, чтобы начать с 10; т.е. мне нужно переименовать B/2022222.1ext в B/1022222.1ext

Я видел много других вопросов, касающихся переименования нескольких файлов, но не мог заставить его работать для моего дела. Просто, чтобы узнать, могу ли я понять, что я делаю, прежде чем на самом деле попытаюсь сделать копию/переименование, которое я сделал:

for file in "*/20?????.*"; do
    echo "{$file/20/10}";
done

но все, что я получаю, это

{*/20?????.*/20/10}

Может кто-нибудь покажет мне, как это сделать?

Ответ 1

У вас просто немного неправильного синтаксиса:

for file in */20?????.*; do mv $file ${file/20/10}; done
  • Удалите кавычки из аргумента in. В противном случае расширение имени файла не происходит.
  • $ в подстановке должен идти до скобки

Ответ 2

Вот решение, которое использует команду find:

find . -name '20*' | while read oldname; do echo mv "$oldname" "${oldname/20/10}"; done

Эта команда фактически не выполняет ваши ставки, она только распечатывает, что делать. Просмотрите вывод, и если вы счастливы, удалите команду echo и запустите ее для реального.

Ответ 3

Просто добавьте ответ "Взрывные таблетки". Однако на OS X вы должны сказать

mv "${file}" "${file_expression}"

Или команда mv не распознает ее.

Ответ 4

Расширения скобки, такие как:

{*/20?????.*/20/10}

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

Вместо этого попробуйте сделать (с Perl rename):

rename 's/^10/^20/' */*.ext 

Вы можете сделать это, используя инструмент Perl rename из приглашения shell. (Есть другие инструменты с тем же именем, которые могут или не могут это сделать, поэтому будьте осторожны.)

Если вы хотите выполнить сухой прогон, чтобы убедиться, что вы не сбиваете какие-либо файлы, добавьте в команду команду -n.

Примечание

Если вы запустите следующую команду (linux)

$ file $(readlink -f $(type -p rename))

и у вас есть результат, например

.../rename: Perl script, ASCII text executable

то это кажется правильным инструментом =)

Кажется, это команда по умолчанию rename на Ubuntu.

Сделать значение по умолчанию Debian и производным, как Ubuntu:

sudo update-alternatives --set rename /path/to/rename

Ответ 5

Поведение глобуса * подавляется в двойных кавычках. Пытаться:

for file in */20?????.*; do
    echo "${file/20/10}";
done