3

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

  • 00000010
    • 000000001.file1
    • 000000001.file2
  • 00000020
    • 00000003.file1
    • 00000003.file2
    • 00000003.file3
  • ...

Таким образом, есть папки с 8-значными именами, содержащими один или несколько файлов, имена которых начинаются с 8-значных чисел. Но эти имена файлов - скажем так - не синхронизированы. Итак, теперь я пытаюсь рекурсивно переименовать их в bash для архивирования:

  • 00000010
    • 000000010.file1
    • 000000010.file2
  • 00000020
    • 00000020.file1
    • 00000020.file2
    • 00000020.file3
  • ...

Мой сценарий выглядит так:

#! /bin/bash

find * -maxdepth 1 -name "*" -type d | while read -r dir
do
        rename 's/$dir\/[0-9]{8}/$dir/' *
done

Но это не работает и дает такие ошибки, как

Глобальный символ "$ dir" требует явного имени пакета в (eval 1) строке 1.

Как я мог написать это, чтобы переименовать файлы в соответствии с именами их папок?

Спасибо за помощь!

2 ответа2

2

Как из другого ответа я узнал, что я должен использовать

rename "s/$dir\/[0-9]{8}/$dir\/$dir/" $dir/*

На всякий случай, если у кого-то есть такая же проблема ...

0

Мне не очень нравится ответ, где $dir интерполируется в шаблон. Это может привести к неожиданным результатам, если каталог будет содержать символ, который интерпретируется как специальный токен регулярного выражения.

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

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

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

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

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

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .