Скрипт оболочки для переименования нескольких файлов из имен их родительских папок

Скрипт оболочки для переименования нескольких файлов из имен их родительских папок

У меня такая структура файла:

  • 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 $diris interpolated into the pattern. Это может привести к неожиданным результатам, если каталог будет, например, содержать символ, который будет интерпретироваться как специальный токен регулярного выражения.

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

rename 's#([^/]+)/[^/]+(\.file[0-9]+)$#$1/$1$2#' base_directory/*/*

где глоб попадает в отдельные файлы в каталогах (можно даже указать base_directory/*/*.file*, или что-то подобное, но здесь это не имеет значения).

Обратите внимание, что это полная команда, без необходимости в findконструкции.

  • Я использую #as разделитель вместо «regular», /чтобы избежать необходимости экранировать его в шаблонах.
  • Я захватываю (жадную) группу "не разделитель каталогов", за которой следует разделитель каталогов, за которым следует имя файла и конец строки. Это делает первую группу захвата родительским каталогом для каждого файла.
  • Первая часть имени файла отбрасывается, за исключением окончания, чтобы сохранить порядковый суффикс.

Я решил использовать более общий подход, а не предполагать, что все файлы имеют длину 8 символов, но реальная разница в том, что мне не нужна ни конструкция, findни втискивание $dirпеременной в (возможно, небезопасную) среду регулярных выражений.

Связанный контент