У меня такая структура файла:
- 00000010
- 000000001.файл1
- 000000001.файл2
- 00000020
- 00000003.файл1
- 00000003.файл2
- 00000003.файл3
- ...
Итак, есть папки с 8-значными именами, содержащие один или несколько файлов с именами, начинающимися с 8-значных чисел. Но эти имена файлов, скажем так, не синхронизированы. Так что теперь я пытаюсь переименовать их рекурсивно в bash в архив:
- 00000010
- 000000010.файл1
- 000000010.файл2
- 00000020
- 00000020.файл1
- 00000020.файл2
- 00000020.файл3
- ...
Мой сценарий выглядит так:
#! /bin/bash
find * -maxdepth 1 -name "*" -type d | while read -r dir
do
rename 's/$dir\/[0-9]{8}/$dir/' *
done
Но это не работает и выдает ошибки типа
Глобальный символ «$dir» требует явного указания имени пакета в строке 1 (eval 1).
Как мне написать, чтобы переименовывать файлы в соответствии с именами их папок?
Спасибо за помощь!
решение1
Как я узнал из другого ответа, мне нужно использовать
rename "s/$dir\/[0-9]{8}/$dir\/$dir/" $dir/*
На всякий случай, если у кого-то возникнет такая же проблема...
решение2
Мне не очень нравится ответ where $dir
is interpolated into the pattern. Это может привести к неожиданным результатам, если каталог будет, например, содержать символ, который будет интерпретироваться как специальный токен регулярного выражения.
Я бы предпочел сопоставлять файлы непосредственно в шаблоне, избегая необходимости перебирать каталоги и просто используя обычный глоб.
rename 's#([^/]+)/[^/]+(\.file[0-9]+)$#$1/$1$2#' base_directory/*/*
где глоб попадает в отдельные файлы в каталогах (можно даже указать base_directory/*/*.file*
, или что-то подобное, но здесь это не имеет значения).
Обратите внимание, что это полная команда, без необходимости в find
конструкции.
- Я использую
#
as разделитель вместо «regular»,/
чтобы избежать необходимости экранировать его в шаблонах. - Я захватываю (жадную) группу "не разделитель каталогов", за которой следует разделитель каталогов, за которым следует имя файла и конец строки. Это делает первую группу захвата родительским каталогом для каждого файла.
- Первая часть имени файла отбрасывается, за исключением окончания, чтобы сохранить порядковый суффикс.
Я решил использовать более общий подход, а не предполагать, что все файлы имеют длину 8 символов, но реальная разница в том, что мне не нужна ни конструкция, find
ни втискивание $dir
переменной в (возможно, небезопасную) среду регулярных выражений.