Bash - Nom d'archive au nom de fichier, correspondance incorrecte (zip, cdg, mp3)

Dec 07 2020

J'ai écrit un script qui vérifie deux extensions particulières dans une archive zip. Quelques vérifications sont effectuées pour déterminer si l'archive ne contient que 2 fichiers, puis les traiter. Si l'archive en a moins de 2, elle déplacera l'archive dans un dossier "MAUVAIS". Si l'archive en contient plus de 2, elle déplacera l'archive vers un répertoire "FIX".

L'étape du processus consiste à extraire les fichiers et à les renommer sous le même nom que l'archive zip.

Tout cela fonctionne bien, lorsque les conditions sont parfaites. Mais quand ils ne sont pas parfaits ... ça devient moche.

Je rencontre un cas où même si les fichiers peuvent avoir les 2 fichiers et l'extension corrects, si les fichiers ont des caractères spéciaux (tels que Ø, backticks, virgule, apostrophe, etc.) ... ils sont traités (je suppose) comme la syntaxe ou les expressions regex.

Voici le code:

#! /bin/bash

prefix="0000_"

mkdir -p ${prefix}{DONE,FIX,BAD} shopt -s nocaseglob for i in *.ZIP; do zip_name="$i"
        pair_exists=$(unzip -Z1 "$i" | grep -E -- '.cdg|.CDG|.mp3|.MP3' | wc -l)
        log="${prefix}LOG.txt" if [ $pair_exists -eq 2 ]
            then
                cdg_name=$(unzip -Z1 "$i" | grep -E -- '.cdg|.CDG' | awk '{print substr($0,index($0,$1))}') mp3_name=$(unzip -Z1 "$i" | grep -E -- '.mp3|.MP3' | awk '{print substr($0,index($0,$1))}')
                new_cdg_name="$(echo "${zip_name%.*}.cdg")"
                new_mp3_name="$(echo "${zip_name%.*}.mp3")"
                7za x "$i" -aoa -y -ba >> ./$log
                mv ./"$cdg_name" ./"$new_cdg_name"
                mv ./"$mp3_name" ./"$new_mp3_name"
                mv ./"$zip_name" ./${prefix}DONE/

        elif [ $pair_exists -gt 2 ] then echo "" echo "NEEDS FIXED: $zip_name"
                mv ./"$zip_name" ./${prefix}FIX/

        elif [ $pair_exists -lt 2 ] then echo "" echo "ARCHIVE IS BAD: $zip_name"
                mv ./"$zip_name" ./${prefix}BAD/

        else
                echo ""
                echo "MUST BE BROKE!"
                echo ""
        fi
    done
exit

Tout est cool, jusqu'à ce que j'arrive aux déclarations mv.

                mv ./"$cdg_name" ./"$new_cdg_name"
                mv ./"$mp3_name" ./"$new_mp3_name"

Je pense que peut-être mv n'est peut-être pas la bonne méthode à utiliser ici, mais j'avais également de sérieux problèmes avec le changement de nom. Je pense plus que j'ai besoin d'un code qui dit aux commandes de ne pas traiter les caractères dans les variables comme des actions à effectuer.

Voici ce que je vois arriver ...

----- EXEMPLE 1 -----

NOM DU FICHIER ZIP: 

     CB30035-05 - PLAN SIMPLE - JE FAIS RIEN.zip

FICHIERS DANS ZIP:

     CB30035-05 - Plan simple - je ferais n'importe quoi.cdg
     CB30035-05 - Plan simple - Je ferais n'importe quoi.mp3

ERREUR:

     mv: cannot stat './CB30035-05 - Simple PlanI \' d Do Anything.cdg ': aucun fichier ou répertoire de ce type
     mv: impossible de stat './CB30035-05 - Simple PlanI \' d Do Anything.mp3 ': aucun fichier ou répertoire de ce type

----- EXEMPLE 2 -----

NOM DU FICHIER ZIP:

     CBSE5-0068 - CARPENTERS, LE - POUR TOUT CE QUE NOUS SAVONS.zip

FICHIERS DANS ZIP:

     cbscdge450-5-0068 - Charpentiers - Pour tout ce que nous savons.cdg
     cbscdge450-5-0068 - Charpentiers - Pour tout ce que nous savons.mp3

ERREUR:
mv: cannot stat './cbscdge450-5-0068 - Carpenters - For All We Know.cdg \ ncbscdge450-5-0068 - Carpenters - For All We Know.mp3': Aucun fichier ou répertoire de ce type

J'ai cherché un problème similaire, mais les sujets que j'ai trouvés ne correspondaient pas vraiment à mon problème ou une partie du code était un peu au-dessus de ma tête pour essayer de comprendre comment l'intégrer dans mon script.

J'apprécierais toute aide. Merci!

(REMARQUE: je suis conscient que mon "awk" dans le script ci-dessus ne fait rien. Je suis passé à "décompresser -Z1" et cela semble avoir résolu mes efforts précédents pour simplement extraire le nom de fichier des fichiers zip. J'ai quitté et l'ajustement juste pour le garder au cas où j'en aurais besoin.)



EDIT 2020120601:


En réponse à @Wieland, j'ai supprimé le double espace du nom du fichier zip. Mais laissé le double espace sur les fichiers à l'intérieur. Je ne serai pas en mesure de réparer l'intérieur de chaque fichier car il y en a trop, donc je dois trouver comment les réparer tels quels. La suppression du double espace sur le fichier zip n'a pas changé mes résultats.

En réponse à @steeldriver, voici un peu plus d'informations. Vous trouverez ci-dessous le retour de chacune des commandes que j'ai tenté d'utiliser (notez le 7za ... il n'a pas de moyen de simplement produire des noms de fichiers, donc j'utilisais awk précédemment).

J'ai également changé le code pour lire et cela n'a pas changé mes résultats, mais je suis d'accord pour couvrir cette base.\.cdg$|\.CDG$|\.mp3$|\.MP3$

zipinfo -1 "CB30035-05 - PLAN SIMPLE - JE FAIS N'IMPORTE QUOI.zip" 

  CB30035-05 - Plan simpleJe ferais n'importe quoi.cdg
  CB30035-05 - Plan simple, je ferais n'importe quoi.mp3

unzip -Z1 "CB30035-05 - PLAN SIMPLE - JE FAIS RIEN.zip" 

  CB30035-05 - Plan simpleJe ferais n'importe quoi.cdg
  CB30035-05 - Plan simple, je ferais n'importe quoi.mp3

7za -ba l "CB30035-05 - PLAN SIMPLE - JE FAIS RIEN.zip"           

   2003-06-27 14:41:56 .... A 1516512 379652 CB30035-05 - Simple PlanI'd Do Anything.cdg
   2003-06-27 14:42:22 .... A 3369876 3112004 CB30035-05 - Simple PlanI'd Do Anything.mp3



MODIFIER 2020120701:


@ G-Man dit 'Réintégrer Monica'

Merci d'avoir mis autant de détails autour de vos explications. J'apprécie cela. J'incorporerai vos suggestions de mods au script. En ce qui concerne

Si vous "avez changé le code pour lire .cdg$|.CDG$| .mp3$|.MP3$ et cela n'a pas changé mes résultats », alors vous vous êtes trompé ...

Je suis presque sûr d'avoir suivi votre exemple de près. J'avais commenté en disant que j'avais fait cela, mais la barre oblique inverse a été supprimée de ma remarque. J'avais également déjà implémenté le grep "c". Mais apparemment raté sérieusement l'option "i". Cela nettoierait certainement cela.

Voici le code tel qu'il se présente maintenant ...

#! /bin/bash

prefix="00001_"

mkdir -p ${prefix}{DONE,FIX,BAD} shopt -s nocaseglob for i in *.ZIP; do zip_name="$i"
        pair_exists=$(unzip -Z1 "$i" | grep -Eci -- '\.cdg$|\.mp3$')

        if [ $pair_exists -eq 2 ] then cdg_name=$(unzip -Z1 "$i" | grep -E -- '\.cdg$|\.CDG$') mp3_name=$(unzip -Z1 "$i" | grep -E -- '\.mp3$|\.MP3$') base_name="${zip_name%.*}"
                new_cdg_name="$base_name.cdg" new_mp3_name="$base_name.mp3"

                        printf 'cdg_name = [%s]\n' "$cdg_name" printf 'mp3_name = [%s]\n' "$mp3_name"

                unzip -qq "$i" mv -- "${cdg_name}" "${new_cdg_name}" mv -- "${mp3_name}" "${new_mp3_name}" mv ./"$zip_name" ./${prefix}DONE/ elif [ $pair_exists -gt 2 ]
            then
                echo ""
                echo "NEEDS FIXED: $zip_name" mv ./"$zip_name" ./${prefix}FIX/ elif [ $pair_exists -lt 2 ]
            then
                echo ""
                echo "ARCHIVE IS BAD: $zip_name" mv ./"$zip_name" ./${prefix}BAD/

        else
                echo ""
                echo "HMM"
                echo ""
        fi
    done
exit

J'ai également intégré vos modifications.

En ce qui concerne un débogage, j'avais de nouveau utilisé "echo". C'est ce que contient mon script de test ...

echo ""
echo "-----"
echo   $pair_exists
echo   $zip_name echo $cdg_name
echo   $mp3_name echo $new_cdg_name
echo   $new_mp3_name echo $prefix
echo   $log
echo "-----"
echo ""

Il produisait la même chose que votre "printf". Cependant, j'aime beaucoup vos manières fantaisistes et adopterai votre style. :)

Pour répondre au point 5. J'ai eu cette idée en utilisant 7z.exe. En fait, en regardant à travers une interface graphique. Maintenant, je vais publier une capture d'écran de ce que voit ma boîte Windows et à nouveau je publierai ce que ma boîte Linux produit.

WINDOWS :

LINUX :

Je n'ai aucune idée pourquoi cela se produit. Après avoir regardé ça pendant un moment, une partie de moi pense juste peut-être ... J'ai foiré mon environnement d'une manière ou d'une autre. Je n'ai jamais traversé un problème comme celui-ci auparavant, et cela me laisse tirer les cheveux!

MAINTENANT! Après vous avoir donné toutes ces informations, et peut-être que je ne vous en ai pas donné assez. Mais j'ai besoin de te le dire. Après avoir apporté vos modifications au code, il produit le résultat correct! Même si mon système supprime toujours le "-" des noms de fichiers, il produit le résultat final souhaité. Je voulais que les fichiers prennent le nom du fichier zip et c'est ce qu'il fait maintenant.

Les changements que j'ai faits ...

  1. nettoyé le pair_exists avec
    unzip -Z1 "$i" | grep -Eci -- '\.cdg$|\.mp3$'

  2. nettoyer l'extraction cdg et mp3_name et supprimer le awk
    cdg_name=$(unzip -Z1 "$i" | grep -E -- '\.cdg$|\.CDG$')
    mp3_name=$(unzip -Z1 "$i" | grep -E -- '\.mp3$|\.MP3$')

  3. incorporé la nouvelle suggestion de base_name et la suppression de l'écho
    base_name="${zip_name%.*}"
    new_cdg_name="$base_name.cdg"
    new_mp3_name="$base_name.mp3"

  4. ajouté les lignes de débogage "printf" (les commentera lors de la création d'un fichier 150k +)
    printf 'cdg_name = [%s]\n' "$cdg_name"
    printf 'mp3_name = [%s]\n' "$mp3_name"

  5. Je change le décompresseur pour décompresser pour rester cohérent avec l'ensemble d'outils
    unzip -qq "$i"

Je ne sais pas où le correctif est arrivé, mais j'apprécie vraiment votre aide @ G-Man dit 'Réintégrer Monica' et m'aider à traverser cela et donner des conseils très solides.

Merci!


Réponses

1 G-ManSays'ReinstateMonica' Dec 07 2020 at 21:17
  1. Le commentaire de steeldriver identifie presque certainement une partie du problème. Si vous «avez changé le code en lecture et que cela n'a pas changé mes résultats», alors vous l'avez mal fait - en particulier, vous l'avez fait de manière incomplète. Une partie du problème réside dans la commande\.cdg$|\.CDG$|\.mp3$|\.MP3$

    cdg_name=$(unzip -Z1 "$i" | grep -E -- '.cdg|.CDG' | awk '{print substr($0,index($0,$1))}')
    

    qui doit être changé en

    cdg_name=$(unzip -Z1 "$i" | grep -E -- '\.cdg$|\.CDG$' | awk '{print substr($0,index($0,$1))}')
    

    parce que correspond , et est donc réglé sur la concaténation des deux noms , séparés par une nouvelle ligne.   Cela ressort clairement du message d'erreur.cbscdge450-5-0068 - Carpenters ….cdgcdg_namemv

  2. Juste à des fins de simplification, vous pourriez changer

    unzip -Z1 "$i" | grep -E -- '\.cdg$|\.CDG$|\.mp3$|\.MP3$' | wc -l
    

    à

    unzip -Z1 "$i" | grep -Ec -- '\.cdg$|\.CDG$|\.mp3$|\.MP3$'
    

    (en utilisant l' option c ount de grep) ou même

    unzip -Z1 "$i" | grep -Eci -- '\.cdg$|\.mp3$'
    

    (en utilisant l' option i gnore case de grep).

  3. Il n'y a pratiquement jamais de raison de le dire . En fait, j'ai tendance à dire qu'il n'y a jamais de raison de faire cela, mais quelqu'un identifiera probablement un cas étrange où cela est bénéfique. Plus précisément,$(echo "something")

    new_cdg_name="$(echo "${zip_name%.*}.cdg")"
    new_mp3_name="$(echo "${zip_name%.*}.mp3")"
    

    peut être changé en

    new_cdg_name="${zip_name%.*}.cdg" new_mp3_name="${zip_name%.*}.mp3"
    

    Je pourrais même aller jusqu'à les changer en

    base_name="${zip_name%.*}" new_cdg_name="$base_name.cdg"
    new_mp3_name="$base_name.mp3"
    

    PS À proprement parler, les citations ci-dessus ne sont pas nécessaires, mais il est bon de les utiliser tout le temps, sauf si vous avez une bonne raison de ne pas le faire.
    PPS Dans le mauvais contexte, pourrait faire des choses comme changer en (c'est- à -dire, compresser plusieurs espaces en un).$(echo "something")Plan  - IPlan - I

  4. Au risque d'être politiquement incorrect, imaginez que vous êtes la police qui tente de résoudre un crime et que tout ce que vous pouvez faire est de vous asseoir devant le quartier général des criminels avec des jumelles. Ne serait-il pas tellement mieux si vous pouviez obtenir une écoute électronique ou un informateur, pour savoir ce qui se passait à l'intérieur du bâtiment? Le débogage, c'est comme essayer de résoudre un crime - alors que les informations externes (c'est-à-dire la sortie de zipinfoet 7za, exécutées séparément) sont importantes pour comprendre le problème, elles aident vraiment à obtenir les informations internes. Donc, comme étape de débogage de routine, je recommande d'ajouter des instructions comme

    printf 'cdg_name = [%s]\n' "$cdg_name" printf 'mp3_name = [%s]\n' "$mp3_name"
    

    au script. Cela aurait rendu évident que cdg_namese préparait à la concaténation des deux noms, et cela pourrait vous aider à localiser les I'd Do Anythingchangements I\'d Do Anything.

  5. À proprement parler, cela devrait être un commentaire, mais tant que je suis ici: d'où avez-vous eu l'idée que les noms des fichiers membres à l'intérieur CB30035-05 - SIMPLE PLAN - I'D DO ANYTHING.zipétaient

    • CB30035-05 - Simple Plan - I'd Do Anything.cdg et
    • CB30035-05 - Simple Plan - I'd Do Anything.mp3

    quand vous ne nous avez montré aucune commande qui montre quoi que ce soit entre le  Planet le  I?

  6. Comme je l'ai mentionné ci-dessus, I\'d Do Anythingc'est un casse-tête. Mais avez-vous réellement des exemples de problèmes liés aux virgules, aux backticks ou aux caractères non ASCII (comme «é», «Φ», «Ø», «θ», «½» ou «∞»)?