Недавно я конвертировал все свои файлы FLAC на более низкую частоту дискретизации 44,1 кГц и битовую глубину 24 бита (потому что iPhone / iPod не поддерживает ничего выше этого), используя XLD на моей Mac OS 10.7 (Lion).
Хотя я сказал XLD перезаписать все предыдущие файлы, XLD добавил (1)
в конце самого файла, как из
some_song.m4a
в
some_song(1).m4a
Итак, теперь я хочу удалить это (1)
из всех файлов FLAC, которые я конвертировал.
Я знаю, что, возможно, мог бы использовать какую-то программу или даже AppleScript для переименования файлов, но я хотел научиться, используя старый способ командной строки.
Я знаю, что find . -name *\(1\).m4a
захватит все преобразованные файлы FLAC.
Далее я знаю, что должен что-то сделать -exec
и mv
переименовать все найденные файлы. Но я не могу понять, как сохранить исходное имя файла и удалить только (1)
.
Может быть, мне нужно сделать захват некоторых групповых регулярных выражений, чтобы сохранить часть имени файла, которую я не хочу изменять? Или, возможно, невозможно сделать все в одной строке, и я должен создать сценарий оболочки (что мне не очень удобно, но я хочу попробовать).
Любые советы или предложения приветствуются! Благодарность!
find
), но который может решить вашу реальную проблему (преобразование аудиофайлов), вам может быть интересно взглянуть на audiotools.sourceforge.net и на этот пример (для macosx lion) invibe.net/ LaurentPerrinet / SciBlog / 2012-04-22Ответы:
Не пытайтесь анализировать
find
вывод, кроме как в крайнем случае. Важно понимать, что в файловых системах Unix имена файлов - это не строки (распространенное заблуждение), а двоичные двоичные объекты, которые могут содержать любой символ, кроме/
символа NULL. Парсинг имен файлов безопасно и корректно - это достаточно тяжело, так что в 99% случаев вам просто захочется вообще этого не делать (просто посмотрите, насколько волосатым являетсяsed
выражение в ответе @ yarek, и даже если оно не охватывает все случаи) , К счастью, в этом случае есть гораздо более простой подход:источник
done
?sed
канальным подходом в том, что это намного безопаснее. Его все еще легче читать, чем суп с обратной косой чертой, если вы понимаете некоторые базовые конструкции сценариев оболочки.$arg
переменная облегчает чтение.find
вызываетsh
довольно переносимый синтаксис POSIX. Для получения более подробной информации вы можете ознакомиться с разделом «Расширение параметров» , разделом о сложных командах, объясняющихfor
цикл , и спецификацией POSIXfind
. В дополнение к этим ресурсам, я был бы рад ответить на любые ваши конкретные вопросы.На Debian и Ubuntu я могу использовать
rename 's/\(1\)//' *.m4a
для решения вашей проблемы.источник
man rename
, но на самом деле у меня нетrename
:-bash: rename: command not found
(which rename
ничего не показывает).man -a rename
находит rename (2) - системный вызов, и rename (n) - команда TCL. Там нет ни переименования (1), ни самой утилиты.rename
это Perl-скрипт, включенный в примеры, включенные в некоторые установки Perl, и пара дистрибутивов включают его в путь, потому что это удобная команда. (@Hobbes, возможно, вы можете найти его в Интернете)rename
- это обычный двоичный файл (не perl). Однако еще одно предостережение заключается в том, что не все версииrename
поддерживают регулярные выражения. Например, у меня есть версия, которая позволяет вам выполнять прямую замену строк, например,rename '(1)' '' *.m4a
rename
Скрипт Perl устанавливается только Debian и его производными. Другие системы Linux имеют другуюrename
утилиту (показанную Патриком). OSX не имеет ни того, ни другого.В zsh, используя zmv :
Во втором аргументе (новое имя)
$1
и$2
ссылаются на заключенные в скобки группы(PATTERN)
в исходном шаблоне. Еще один способ написания этого переименованияисточник
Следующий подход дает вам возможность предварительного просмотра / сокращения сгенерированных команд перед их выполнением, и он очень переносим: он должен работать не только на Mac, не только с bash, но и не только с GNU sed; даже в системах без команды
find
(1) можноdu
без проблем заменить ее на (1).Если вы довольны напечатанными командами, перезапустите с
| sh -x
добавлением.Если вам нужны пробелы в именах файлов, добавьте еще один s для экранирования всех пробелов:
Если ожидаются другие специальные символы, это немного сложнее:
Первая функция преобразует все
'
в такую форму, что они воспринимаются буквально в середине'...'
строки -escaped. Вторая функция генерирует команды mv , аргументы которых заключены в'...'
.источник
(
и все другие специальные символы) и не добавляет кавычки вокруг имени файла. Я попытался изменить вашу команду, но я не мог понять, как добавить кавычки вокруг обоих имен файлов дляmv
команды. Один из полученного выхода из вашей команды естьmv ./The Beatles - Let It Be (MFSL LP 1-109) 24-96 Vinyl Rip/01 Two Of Us(1).m4a ./The Beatles - Let It Be (MFSL LP 1-109) 24-96 Vinyl Rip/01 Two Of Us.m4a
. И если я выполню эту команду, я получу-bash: syntax error near unexpected token '('
.e
команду после подстановки. Например,find . -name '*(1).m4a' | sed 's/\(.*\)(1).m4a$/mv & \1.m4a/e'
будет выполнять команду без передачи вsh -x
.Вот небольшой скрипт, который делает это:
источник
`find ...`