2010-04-25 10 views
6

J'ai vu des boucles pour décompresser tous les fichiers zip dans un répertoire. Cependant, avant que je cours, je préférerais vous assurer que je suis sur le point d'exécuter fonctionnera droite:Une boucle shell peut-elle décompresser tous les fichiers d'un répertoire?

for i in dir; do cd $i; unzip '*.zip'; rm -rf *.zip; cd ..; done 

Fondamentalement, je veux regarder à la sortie de voir « dir » tous les dossiers, pour chaque Cd dans le répertoire, décompressez toutes les archives zip, puis supprimez-les, puis cd retour et recommencez jusqu'à ce qu'il n'y en a plus.

Est-ce quelque chose que je devrais faire dans une seule commande ou devrais-je envisager de le faire en Perl?

+1

Bonjour et bienvenue sur StackOverflow. Pour rendre votre code plus lisible, veuillez utiliser l'étiquette de code –

+1

pour votre information, vous pouvez utiliser cd - pour revenir dans le répertoire précédent. – Aif

+0

@Patrick fait :) – DVK

Répondre

1

testé en partie:

find . -type d -exec sh -c "cd \"{}\" ; unzip \"*.zip\" ; rm \"*.zip\" " \; 

exécute la chaîne cd/unzip/rm pour chaque subdir.

+0

Jusqu'à présent cela fonctionne, où l'autre réponse ne pouvait pas prendre des choses comme "Nom du dossier avec un espace", mais il ne supprime pas les archives .zip. – helpwithshell

+0

Je pense que vous devez utiliser 'trouver ... | xargs -0 ... 'pour gérer les espaces, ou les guillemets échappés font-ils le travail? – Anycorn

+0

À la fin, j'ai été en mesure de modifier votre ligne de commande à: trouver. -name "* .zip" -exec sh -c "rm -rf \" {} \ "" \; pour supprimer toutes les archives .zip restantes. merci – helpwithshell

1

Utilisez * pour obtenir le contenu du répertoire courant:

for i in *; do cd "$i"; ...etc... ; done 

Vous devez également vous assurer que quelque chose est un répertoire avant d'essayer de cd dedans. En bash cela se fait comme suit:

if [ -d "$i" ]; then ...etc... ; fi 

Vous devez également prendre soin de vérifier que l'opération a réussi Décompressez avant de supprimer le fichier zip. Il n'est pas nécessaire d'utiliser la suppression de force récursive pour supprimer un seul fichier.

Je pense que cela pousse la limite pour ce qu'il est raisonnable de faire une seule ligne. Mettez-le dans un script shell et formatez-le sur plusieurs lignes.

2

Vous devriez être bien en général. Pour le débogage, le préfixe de toutes les commandes dans la boucle avec echo vous dira comment les variables se développent. Vous pouvez également toujours utiliser rm -i pour être demandé au lieu de faire rm aller de l'avant avec quoi que ce soit avec -f. Les guillemets simples dans votre appel unzip ne décompresseront que les fichiers nommés *.zip, c'est-à-dire que le * ne se développera pas. Utilisez plutôt des guillemets doubles (ou pas de guillemets).

Votre boucle suppose maintenant que tous les répertoires $i sont directement sous le répertoire actuel. Une solution plus générale consisterait à utiliser la pile de répertoires (pushd et popd);

for i in $dir; do 
    pushd $i 
    unzip *.zip 
    rm -rf *.zip 
    popd 
done 
+0

J'ai dû changer le premier de pour i dans dir pour i dans *, il a décompressé des choses, mais avait des problèmes avec les fichiers qui contenaient des espaces dans le nom. – helpwithshell

+0

@help: J'ai supposé implicitement que 'dir' était une variable alors que ce n'était pas le cas, mon exemple était faux. Fixé ici et maintenant suppose que 'dir' est une variable contenant la liste du répertoire. –

2

Quelques points ajoutant à ce que les autres ont dit:

  • Si vous mettez un paramètre entre guillemets simples, comme dans '*.zip', la coquille ne fera pas l'expansion de la carte sauvage et décompressez va essayer de traiter une archive cela s'appelle littéralement *.zip
  • N'utilisez pas -r comme un paramètre à rm si vous souhaitez simplement supprimer des fichiers uniques. C'est juste inutilement dangereux car toute suppression récursive de sous-répertoires ne serait probablement pas voulue.
  • Vous devriez vérifier le code de retour de unzip et seulement supprimer le fichier zip si Dézippage a réussi (par exemple, vous pourriez dire if unzip *.zip; then rm *.zip; fi, ou même utiliser une boucle for explicite pour traiter les fichiers zip, un par un)
0

Lorsque vous voulez savoir si quelque chose fonctionne, mais se méfient de c'est des conséquences destructrices, faire un peu à la fois:

Assurez-vous d'obtenir les bons fichiers:

for i in dir; do cd $i; echo $i; cd ..; done 

Assurez-vous que vous pouvez décompresser les fichiers avant de supprimer les fichiers:

for i in dir; do cd $i; unzip '*.zip'; cd ..; done 

Et, avant de faire le plein monty, faire une sauvegarde de votre répertoire.