Странный результат при использовании sed для переименования файлов

Я использую Ubuntu 20.04.2 с GNU sed версии 4.7 . У меня есть куча музыкальных файлов, которые получили странные названия, потому что они не иметь всю указанную мной информацию в имени файла. Например, «Бруно Марс - NA - Бруно Марс - The Lazy Song.aiff» В основном, NA ставится вместо года, потому что это неизвестно. Что я хочу нужно переименовать все эти файлы, чтобы опустить "- NA -" и все, что было до этого, так что файл получился "Bruno Mars - The Lazy Song.aiff"

Вот моя проблема и то, что я пробовал пока: Я скопировал несколько затронутых файлов в другую папку и использовал команду sed 's /^.* NA - //' * , чтобы попытаться исправить именование, но я начал получать очень странный вывод с терминала, см. this . Я попытался переустановить sed, используя переименовать sed 's /^.* NA - //' * и perl -pi -e 's /^.* NA - //' * и ни один из них не работал; однако переименование и perl команды не производили такого же странного вывода, как раньше. Моя интуиция подсказывает мне, что мое регулярное выражение неверно, но в документации сказано, что это должно сработать. Любая помощь приветствуется.Спасибо!

0
задан 4 May 2021 в 22:27

1 ответ

Команда sed 's /^.* NA - //' * не будет переименовывать файлы, она попытается заменить шаблон в содержимом файлов, передавая результат на терминал (с потенциально странные результаты, особенно если расширение * включает любые двоичные файлы).

Команда perl -pi -e 's /^.* NA - //' * будет делать то же самое, за исключением изменения содержимого на месте, что может привести к повреждению ваших файлов.

Чтобы использовать sed (или сам Perl) для переименования файлов, вам нужно сделать что-то вроде

for f in *; do mv -n -- "$f" "$(sed 's/pattern/replacement' <<<"$f")"

или

for f in *; do mv -n -- "$f" "$(printf '%s\n' "$f" | sed 's/pattern/replacement')"

т.е. передача имени каждого файла в sed через стандартный ввод. Однако ваш шаблон можно так же легко написать как замену оболочки, полностью исключив необходимость в sed:

for f in *; do mv -n -- "$f" "${f##* - NA - }"; done

(я предполагаю, что вы также хотите удалить начальный пробел). ## * соответствует самой длинной последовательности ведущих символов, эквивалентной базовому регулярному выражению ^. *

Чтобы использовать Perl под капотом, но изменяя имена файлов , а не содержимого, вам нужна команда rename из пакета rename . (Существуют и другие команды rename , например, из пакета util-linux , которые работают иначе.) Например:

rename -n 's/^.*? - NA - //' *.aiff

(Я ограничил область действия .aiff и сделал соответствие . * не жадным - функция, которую sed не предоставляет, - так что сопоставление выполняется только до первого - NA - на случай, если имеется несколько экземпляров.) Удалите -n , если вас устраивают предлагаемые изменения имен.

2
ответ дан 7 May 2021 в 17:40

Другие вопросы по тегам:

Похожие вопросы: