Bash скрипт для сортировки mp3 файлов по битрейту - PullRequest
1 голос
/ 19 мая 2019

Я взял этот скрипт https://www.linuxquestions.org/questions/linux-newbie-8/finding-corrupt-mp3s-in-library-632053/, который, кажется, изначально отлично работает, и изменил его на этот, чтобы вывести список дорожек ниже 320 кбит / с, но я получил неожиданную ошибку конца файла.Кажется, что одни только команды работают нормально.

find . -maxdepth 1 -iname '*.mp3' -exec sh -c 'curfname="{}";\
      bitrate=`mp3info -r a -p "%f %r\n" "$curfname" | awk 'NF>1{print $NF}'`;\
      if [ $bitrate -lt 320 ];\
      then \
         echo $curfname has $bitrate bitrate; \
      fi ' \; | tee ./lowbitrate.log

Может ли какая-нибудь полезная душа указать, где я неправ?

Редактировать:

Это то, что я получаю

~/bin/mp3bitrate.sh ~/Music
}`;\
      if [ $bitrate -lt 320 ];\
      then \
         echo $curfname has $bitrate bitrate; \
      fi : -c: line 1: unexpected EOF while looking for matching ``'
}`;\
      if [ $bitrate -lt 320 ];\
      then \
         echo $curfname has $bitrate bitrate; \
      fi : -c: line 2: syntax error: unexpected end of file
}`;\
      if [ $bitrate -lt 320 ];\
      then \
         echo $curfname has $bitrate bitrate; \
      fi : -c: line 1: unexpected EOF while looking for matching ``'
}`;\
      if [ $bitrate -lt 320 ];\
      then \
         echo $curfname has $bitrate bitrate; \
      fi : -c: line 2: syntax error: unexpected end of file
}`;\
      if [ $bitrate -lt 320 ];\
      then \
         echo $curfname has $bitrate bitrate; \
      fi : -c: line 1: unexpected EOF while looking for matching ``'
}`;\
      if [ $bitrate -lt 320 ];\
      then \
         echo $curfname has $bitrate bitrate; \
      fi : -c: line 2: syntax error: unexpected end of file

Хорошо, я изменил вторую строку на:

bitrate=`mp3info -r a -p "%r\n" "$curfname"`;\

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

if [ $(echo "$bitrate < 320" | bc ) -e 1 ]

, возвращает: строка 2: [: -e: ожидается двоичный оператор

, но выполняется только командапохоже на работу:

echo "234.54444444 <320" |bc </p>

возвращает 1, что сейчас не так, мне интересно!

Ответы [ 2 ]

1 голос
/ 19 мая 2019

Попробуйте:

mp3info -r a -p "%f has %r bitrate\n" ./*.[Mm][Pp]3 | awk '$(NF-1)<320'

Как это работает:

  • -p "%f has %r bitrate\n" печатает информацию в нужном формате.

  • awk '$(NF-1)<320' выбирает только те строки с битрейтом, меньшим 320.

Улучшение

Вышеприведенное не будет выполнено, если само имя файла содержит символы новой строки.Обычный способ справиться с этим - использовать NUL-разделенный вывод, но, насколько я могу судить, mp3info не поддерживает это.В нашем случае вывод никогда не будет содержать /.Это потому, что, хотя / может быть частью пути, оно никогда не является частью имени файла в %f.Таким образом, мы можем использовать:

mp3info -r a -p "%f has %r bitrate/" ./*.[Mm][Pp]3 | awk -v RS=/ '$(NF-1)<320'

Пример вывода

$ mp3info -r a -p "%f has %r bitrate/" ./*.[Mm][Pp]3 | awk -v RS=/ '$(NF-1)<320'
gd77-05-08d1t01.mp3 has 186.720474 bitrate
gd77-05-08d1t02.mp3 has 183.336975 bitrate
gd77-05-08d1t03.mp3 has 183.020111 bitrate
...

Повторение в подкаталоги (безопасная версия)

Для рекурсии через каталог currect и все его подкаталоги, которые ищутфайл с расширениями mp3, мы можем использовать find.Наиболее безопасный подход - использовать find с -execdir:

find . -iname '*.mp3' -execdir mp3info -r a -p "%f has %r bitrate/" {} +  | awk -v RS=/ '$(NF-1)<320'

Например:

$ find . -iname '*.mp3' -execdir mp3info -r a -p "%f has %r bitrate/" {} +  | awk -v RS=/ '$(NF-1)<320'
gd77-05-08d1t05.mp3 has 184.018967 bitrate
gd77-05-08d3t05.mp3 has 189.467697 bitrate
gd77-05-08d1t08.mp3 has 183.625366 bitrate
gd77-05-08d1t09.mp3 has 183.826721 bitrate
...

Повторение в подкаталоги (менее безопасная версия)

Если ваш PATH «небезопасен», тогда используйте find с -exec:

find . -iname '*.mp3' -exec mp3info -r a -p "%f has %r bitrate/" {} +  | awk -v RS=/ '$(NF-1)<320'

. Это выдаст тот же результат:

$ find . -iname '*.mp3' -exec mp3info -r a -p "%f has %r bitrate/" {} +  | awk -v RS=/ '$(NF-1)<320'
gd77-05-08d1t05.mp3 has 184.018967 bitrate
gd77-05-08d3t05.mp3 has 189.467697 bitrate
gd77-05-08d1t08.mp3 has 183.625366 bitrate
gd77-05-08d1t09.mp3 has 183.826721 bitrate
...
0 голосов
/ 19 мая 2019

Да!Я нашел решение!

#!/bin/bash
#
find . -maxdepth 3 -iname '*.[Mm][Pp]3' -exec sh -c 'curfname="{}";\
      bitrate=`mp3info -r a -p "%r\n" "$curfname"`;\
      if (( $(echo "$bitrate < 320" |bc -l) ));\
      then \
         echo $curfname has $bitrate bitrate; \
      fi ' \; | tee ./lowbitrate.log

Успешно отсканирует местоположение, повторяющееся до глубины 3, напечатав в терминале и войдя в систему, чтобы записать любые найденные mp3-файлы с битрейтом ниже 320 Кбит / с.

Как мне переместить каждый из этих файлов в новый каталог, сохранив исходную структуру?Потому что даже если я сделаю:

...
      then \
         location="${curfname:2}";\
         mv "$curfname" "lowbitrate/$location";\
         echo $curfname has $bitrate bitrate;\
...

Мне все еще нужно рекурсивно использовать mkdirs, есть идеи?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...