Bash脚本按比特率对mp3文件进行排序

时间:2019-05-19 15:20:18

标签: linux bash

我已经使用了这个脚本 https://www.linuxquestions.org/questions/linux-newbie-8/finding-corrupt-mp3s-in-library-632053/最初似乎运行良好,然后将其修改为列出低于320 kbps的音轨,但出现了意外的文件错误结尾。 不过,仅这些命令似乎可以正常工作。

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,因为那会引起问题。 但是现在我有了一个浮点数和整数的比较,用// p>更改了if语句。

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

返回:第2行:[:-e:需要二进制运算符

但仅运行命令似乎可以工作:

回显“ 234.54444444 <320” |公元前

返回1,我想知道现在出了什么问题!

3 个答案:

答案 0 :(得分:1)

尝试:

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
...

答案 1 :(得分:0)

是的!我找到了解决方案!

#!/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的位置,在终端中打印并记录所有比特率低于320 Kbps的mp3文件。

我该如何将这些文件中的每个文件移动到一个保留原始结构的新目录中? 因为即使我这样做:

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

我仍然需要递归mkdirs,有什么想法吗?

答案 2 :(得分:0)

我还需要按比特率对mp3进行排序,但是我还需要将其复制到另一个目录中,并且我想保留“ Musique”文件夹的原始结构。所以我这样做了。当然不是完美的,但是它是可行的;)

#!/bin/bash
## That script search for mp3 with high bitrate (equal to 320) and copy it to another directory
## and keep the original file structure
mp3_path="/home/user/Musique/"
copy_path="/media/disk/"

while read FILENAME
do

    f=$FILENAME
    path=${f%/*}
    xfile=${f##*/}
    title=${xfile%.*}
    ext=${xfile##*.}
    directory=$(dirname "${FILENAME}")

    bitrate="$(mp3info -r m -p "%r\n" "${FILENAME}")"
    # cut "/home/user/Musique/"" from the full path to not recreate it
    path_to_create=$(echo ${directory:19})
    copy_path_to_create=$(echo "$copy_path$path_to_create")

    if [[ "$bitrate" -eq '320' ]] ; then

        echo "$bitrate - $FILENAME" >> /home/user/Musique/texte.txt
        mkdir -p "$copy_path_to_create"
        cp "$FILENAME" "$copy_path_to_create"
    fi

done < <(find "$mp3_path" -type f -name "*.mp3")