Привет, коллеги. Сегодня разберем один прием для работы с файлами. Бывает нужно переименовать много файлов по сложной схеме. Например, заменить в имени файла дату в формате мес.день.год в нормальный день.мес.год, или перевести расширение в нижний регистр, или разложить файлы по папкам в зависимости от типа, или ещё что-нибудь в этом роде.
Кое-что может команда mv, если вы умеете ею пользоваться. Есть однострочники на Перле (или скрипты на других, менее удобных языках), в которых можно настроить логику переименования. Но самый общий способ, позволяющий вообще всё, мы здесь обсудим. Идея взята из Vim.Tips.
Способ такой: получить список файлов в виде текста в буфере Вим, далее средствами Вим превратить его в команды переименования, и отправить на выполнение. Все три этапа можно сделать по-разному.
Можно открыть Вим специально для этой цели: \ls | vim -
Слеш нужен для отключения псевдонимов; гарантированно сработает именно ls без всякого цветового выделения и прочего. Мы получим список файлов в буфере Вим.
Можно из самого Вим сделать так: :r !ls
Далее преобразуем файлы в команды для переименования. Можно выполнить :s/\(.*\)/mv \1 \1/ и потом отредактировать правый столбец вручную. Можно применить средства Вим:
:%s/.*/mv -i '&' \L'&'/g для перевода имен в нижний регистр. Ключ -i предписывает команде mv переспрашивать. Одинарные кавычки нужны, чтобы не было проблем с пробелами в именах файлов. Символ & означает "всё, что совпало": выше мы обошлись захватом, а здесь применили символ. Символ \L обращает всё в нижний регистр до конца.
Приписать расширение к каждому файлу: :%s/.*/mv -i '&' '&.orig'/g
Заменить какой-то текст:
:%s/.*/\="mv -i ".submatch(0)." ".substitute(submatch(0), "foo", "bar", "g")/g
Здесь мы используем вычисляемое выражение подстановки.
Можно сделать то же вручную, например, заменить формат дат.
Ну или вот как разложить файлы по подпапкам (они должны уже иметься, хотя и это можно автоматизировать):
:%$.*\.\(.*\)$mv '&' \1/&$
Далее надо это всё выполнить. Можно сохранить файл, сделать его выполняемым через chmod +x и выполнить. Можно не делать его выполнимым, а просто передать bash:
:!bash %
Или так:
:w !bash
Здесь каждая строчка выполнится отдельно.
А можно так:
:% | !bash
Здесь каждая строка заменится на ответ команды, что может быть полезно.
Можно делать то же на выделении, выполнив только часть команд.
Понятно, что есть всякие удобности и утилиты, но Вим всегда под рукой и там можно вообще всё.