1
votes

Script Bash pour trier les fichiers mp3 par débit

J'ai pris ce script https: //www.linuxquestions .org / questions / linux-newbie-8 / find-corrupt-mp3s-in-library-632053 / qui semble fonctionner correctement à l'origine, et l'a modifié dans celui-ci pour lister les pistes inférieures à 320 kbps mais J'obtiens une erreur de fin de fichier inattendue. Les commandes seules semblent fonctionner correctement.

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

Est-ce qu'une âme utile peut indiquer où je me trompe?

Modifier:

C'est ce que j'obtiens

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

Ok j'ai changé la deuxième ligne avec:

~/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

pour que le awk ne soit pas nécessaire comme cela posait des problèmes. Mais maintenant, j'ai une comparaison avec un flottant et un entier, en changeant l'instruction if avec

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

renvoie: ligne 2: [: -e: opérateur binaire attendu

mais exécuter la commande seule semble fonctionner:

echo "234.54444444

renvoie 1, qu'est-ce qui ne va pas maintenant je me demande!


5 commentaires

Si vous ajoutez la sortie de mp3info à votre question, nous aurons une meilleure idée de la façon de l'analyser.


Si vous nous dites de quelle manière le script que vous avez ne fait pas ce que vous voulez (mauvaise sortie? Pas de sortie? Core dump? Messages d'erreur? Autre chose?), Nous aurons une meilleure idée de comment l'expliquer et le corriger .


Shellcheck produit 13 résultats pour votre code. Vous devez les corriger avant de continuer.


@jww avez-vous coché celui de la réponse ou de la question?


oh oui vous avez exécuté l'ancien code. le dernier dans ma réponse semble bon non? pastebin.com/CtNKKhz8


3 Réponses :


1
votes

Essayez :

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

Comment ça marche:

  • -p "% f a un débit de% r \ n" imprime les informations dans le format souhaité.

  • awk '$ (NF-1) ne sélectionne que les lignes avec un débit inférieur à 320.

Amélioration

Ce qui précède échouera si un nom de fichier lui-même contient des retours à la ligne. La façon habituelle de gérer cela est d'utiliser une sortie séparée par NUL mais, pour autant que je sache, mp3info ne le prend pas en charge. Dans notre cas, la sortie ne contiendra jamais / . En effet, bien que / puisse faire partie d'un chemin, il ne fait jamais partie d'un nom de fichier dans % f . Ainsi nous pouvons utiliser:

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

Exemple de sortie

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

Récursif dans les sous-répertoires (version sécurisée)

Pour parcourir le répertoire currect et tous ses sous-répertoires à la recherche de fichiers avec des extensions mp3, nous pouvons utiliser find . L'approche la plus sûre consiste à utiliser find avec -execdir:

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

Par exemple:

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

Récursivité dans les sous-répertoires (version moins sécurisée)

Si votre PATH est "non sécurisé", alors utilisez find avec -exec:

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

Cela produit la même sortie:

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


7 commentaires

si je remplace votre ligne, j'obtiens: ~ / bin / mp3bitrate.sh ~ / Music /home/apaxio/bin/mp3bitrate.sh: ligne 3: NF-1: commande non trouvée /home/apaxio/bin/mp3bitrate.sh: ligne 3: 320`; \ if [$ bitrate -lt 320]; \ then \ echo $ curfname a $ bitrate bitrate; \ fi: aucun fichier ou répertoire de ce type


@RKon La commande que je montre devrait être votre solution complète . Il ne devrait y avoir aucune instruction if ou echo ou autre chose que ce que je montre.


oh tout seul, il ne renvoie rien? .. et comment serait-il récurer dans les dossiers de la bibliothèque musicale désolé je ne peux pas comprendre.


Dans votre code d'origine, vous aviez -maxdepth 1 . Cela signifie que vous n'avez explicitement pas souhaité la récursion. Si vous voulez une récursion, nous devrons faire un changement.


super merci! mais j'obtiens ceci: find: Le répertoire courant est inclus dans la variable d'environnement PATH, qui n'est pas sécurisée en combinaison avec l'action -execdir de find. Veuillez supprimer le répertoire courant de votre $ PATH (c'est-à-dire supprimer ".", Doublé deux points, ou deux points de début ou de fin) Quel est le danger ?? Savez-vous également, concernant ma réponse, quelle commande déplacerait tous ces fichiers trouvés <320 dans un répertoire préservant la structure des dossiers?


@RKon Désolé pour ça! Je viens d'ajouter une version qui fonctionnera toujours même si votre PATH contient . . (Le problème est que, si votre PATH contient . , il peut essayer d'exécuter n'importe quel fichier nommé mp3info qui se trouve dans votre répertoire actuel au lieu du que vous attendiez. Il s’agit d’une mauvaise surprise potentielle, que vous utilisiez find ou non.)


Très beau tout fait en une seule ligne, merci! Mais de l'autre façon, je vois le chemin complet vers où chercher le fichier. Aussi maintenant j'essaye de déplacer tous les mp3 trouvés dans un sous-répertoire en préservant leur structure de dossiers, un indice?



0
votes

Oui! J'ai trouvé une solution!

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

Balayera avec succès l'emplacement récursif jusqu'à la profondeur 3, imprimant dans le terminal et enregistrant pour classer tous les fichiers mp3 trouvés avec un débit inférieur à 320 Kbps. P >

Comment procéder pour déplacer chacun de ces fichiers dans un nouveau répertoire en préservant la structure d'origine? Parce que même si je fais:

#!/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

J'ai encore besoin de mkdirs récursivement, des idées?


2 commentaires

mkdir -p missing / path / elems créera tous les sous-répertoires nécessaires pour créer le chemin spécifié. Bonne chance.


Oui! un pas de plus, je dois maintenant supprimer le nom de fichier de $ curfname et je serai bien!



0
votes

Je dois aussi trier mon mp3 par bitrate mais je dois aussi le copier dans un autre répertoire et je veux conserver la structure originale de mon dossier "Musique". Alors j'ai fait de cette façon. Certainement pas parfait, mais ça marche;)

#!/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")


0 commentaires