20 июля 2009 г.

Массовое переименование файлов

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

В этих случаях на помощь приходят регулярные выражения и специальные утилиты для массового переименования.

Для меня наиболее удобна консольная утилита prename (или rename), входящая в состав пакета perl. Но кому-то больше по душе, наверное, придутся программы с графическим интерфейсом. Могу посоветовать программы krename или gprename. Однако, в большинстве случаев вполне хватит и prename.

Введение
Синтаксис команды выглядит очень просто:
prename ШАБЛОН ФАЙЛЫ

Но за этой простотой скрывается огромная мощь. Дело в том, что в качестве шаблона используются регулярные выражения.

Параметр ФАЙЛЫ может быть как списком файлов, так и шаблоном в стиле bash, использующим «*» для любой последовательности символов и «?» для одиночного символа. Например, «*.txt» — это все файлы с раширением «txt».

Регулярные выражения
Остановимся поподробнее на регулярных выражениях. Это настолько обширная тема, что о них пишутся целые книги. И настолько сложная, что большую популярность получила известная шутка: «Некоторые люди, когда сталкиваются с какой-то проблемой, думают: “Думаю, я применю регулярные выражения.” Теперь у них две проблемы.» (Jamie Zawinski) Однако, в простых случаях регулярные выражения просты и удобны. Разве что выглядят непривычно. (Честно говоря, иногда они выглядят так, будто по клавиатуре пробежала кошка.)

В утилите prename регулярные выражения обычно имеют следующий вид:
s/ИСХОДНЫЙ/КОНЕЧНЫЙ/
ИСХОДНЫЙ и КОНЕЧНЫЙ — это шаблоны. Первый задает подстроку, которую нужно найти в имени, а второй — на что эту подстроку заменить.

В простейшем случае это могут быть обычные слова. Команда
prename 's/Алиса/Боб/' *.txt
заменит во всех файлах с расширением «txt» слово «Алиса» на слово «Боб».

Нужно заметить, что шаблон применяется к каждому имени файла только один раз. То есть файл с именем «Эх, Алиса, Алиса.txt» будет заменен на «Эх, Боб, Алиса.txt». Чтобы шаблон примянялся столько, сколько нужно, необходимо добавить параметр g к регулярному выражению:
prename 's/Алиса/Боб/g' *.txt
Подстановки
Кроме собственно слов можно использовать специальные подстановочные символы:
«.» — любой одиночный символ,
«\d» — цифра,
«\D» — любой символ кроме цифры,
«\w» — буква, цифра или знак подчёркивания,
«\W» — всё, кроме букв, цифр и знака подчёркивания,
«\s» — любой пробельный символ,
«\S» — любой непробельный символ.

Например, команда
prename 's/\s/_/g' *.txt
заменит пробелы на знаки подчёркивания. Несколько идущих подряд пробелов будут заменены на несколько подчёркиваний.

Начало и конец
Есть также специальные псевдосиволы:
«^» — обозначает начало слова,
«$» — обозначает конец слова.

Например, команда
prename 's/a$/b/' *.txt
заменит «a» на «b» только если «a» — последний символ имени файла.

Экранирование
Если же какой-то из специальных символов нужно использовать в шаблоне как символ обычный, его нужно экранировать обратным слэшем. Например, «.» — одиночный символ, «\.» — просто точка.

Повторы
После любой части регулярного выражения можно поставить количество его повторов:
«?» — ноль или один,
«*» — ноль и более,
«+» — один и более,
«{n}» — ровно n
«{m,n}» — от m до n,
«{m,}» — от m и более,
«{,n}» — от нуля до n.

Символы «?», «+» и «*» по умолчанию являются «жадными», то есть пытаются отхватить как можно большую часть выражения, попадающую под шаблон.

Команда
prename 's/\s+/_/g' *.txt
заменит пробелы на знаки подчёркивания. Несколько идущих подряд пробелов будут заменены на одно подчёркивание.

Группировка и ссылки
Части выражения можно группировать при помощи круглых скобок. Также можно ссылаться на скобки при помощи выражения вида «$номер». Здесь — номер — это номер пары скобок в порядке их вхождения в выражение.

Например, команда
prename 's/(\d)+/$1/g' *.txt
заменит несколько подряд идущих одинаковых цифр в имени на одну (эту же!) цифру. То есть файл с именем «11122233333.txt» будет переименован в «123.txt».

А команда
prename 's/(.*) - (.*)\.mp3/$2 - $1\.mp3/' *.mp3
переименует файл «Ария Филиппа - Шаляпин.mp3» в «Шаляпин - Ария Филиппа.mp3».

Что за там, за горизонтом?
Есть также полезная возможность заглянуть вперед или назад, но не включая определенную часть шаблона в найденное:
«(?=ШАБЛОН)» — просмотр вперёд,
«(?!ШАБЛОН)» — просмотр вперёд (с отрицанием),
«(?<=ШАБЛОН)» — просмотр назад,
«(?<!ШАБЛОН)» — просмотр назад (с отрицанием).

Например, команда
prename 's/(?<!x)a/b/g' *.txt
заменит «a» на «b» в файлах с раширением «txt» только если «a» не идёт после x.

А команда
prename 's/a(?!x)/b/g' *.txt
заменит «a» на «b» в файлах с раширением «txt» только если «a» не идёт перед x.

Заключение
Регулярные выражения имеют огромную область применения. Естественно, в этом посте перечислены далеко не все их возможности. Например, не сказано про транслитерацию или диапазоны символов.

В качестве неплохого руководства по ним могу порекомендовать книгу Дж. Фридла «Регулярные выражения».

У утилиты, конечно, есть и недостатки. Главный очевиден — нужно знать регулярные выражения. Есть и другие. Например, с помощью prename нельзя пронумеровать файлы.

2 комментария: