Je pensais que ce serait simple - mais cela s'avère plus complexe que ce à quoi je m'attendais.
Je veux parcourir tous les fichiers d'un type particulier dans un répertoire, alors j'écris ceci:
#!/bin/bash
for fname in *.zip ; do
echo current file is ${fname}
done
Cela fonctionne tant qu'il y a au moins un fichier correspondant dans le répertoire. Cependant s'il n'y a pas de fichiers correspondants, j'obtiens ceci:
current file is *.zip
J'ai ensuite essayé:
#!/bin/bash
FILES=`ls *.zip`
for fname in "${FILES}" ; do
echo current file is ${fname}
done
Bien que le corps de la boucle ne s'exécute pas lorsqu'il n'y a pas de fichiers, j'obtiens une erreur de ls:
ls: *.zip: No such file or directory
Comment puis-je écrire une boucle qui ne gère correctement aucun fichier correspondant?
shopt -s nullglob
avant d'exécuter la boucle for.FILES=
ls * .zip; for fname in "${FILES}"...
mais cela fonctionne comme prévu avecfor fname in *.zip ; do....
for file in *.zip
pas`ls ...`
. La suggestion de @ cuonglm est de faire en sorte que*.zip
rien ne se développe lorsque le modèle ne correspond à aucun fichier.ls
sans arguments répertorie le répertoire courant.ls
est généralement à éviter: pourquoi ne pas analyserls
? ; voir également le lien en haut de cette page vers l' article ParsingLs de BashGuide .Réponses:
Dans
bash
, vous pouvez définir l'nullglob
option de sorte qu'un modèle qui ne correspond à rien "disparaisse", plutôt que traité comme une chaîne littérale:Dans le script shell POSIX, vous vérifiez simplement qu'il
fname
existe (et en même temps avec[ -f ]
, vérifiez qu'il s'agit d'un fichier normal (ou d'un lien symbolique vers un fichier normal) et pas d'autres types comme répertoire / fifo / device ...):Remplacez
[ -f "$fname" ]
par[ -e "$fname" ] || [ -L "$fname ]
si vous souhaitez parcourir tous les fichiers (non masqués) dont le nom se termine.zip
quel que soit leur type.Remplacez
*.zip
par.*.zip .zip *.zip
si vous souhaitez également prendre en compte les fichiers cachés dont le nom se termine par.zip
.la source
shopt -s nullglob
n'a pas fonctionné pour moi sur Ubuntu 17.04, mais[ -f "$fname" ] || continue
a bien fonctionné.bash
.Dans un commentaire, vous mentionnez ici l'invocation d'une fonction ...
la source
Utilisez find
Vous DEVEZ exporter votre fonction shell avec
export -f
pour que cela fonctionne.find
Exécute maintenantbash
ce qui exécute votre fonction shell, et reste au niveau dir actuel seulement.la source
Au lieu de:
Essayer:
De cette façon, si ls échoue (ce qui se produit dans votre cas), il récupérera la sortie ayant échoué et retournera sous forme de variable vide.
Vous pouvez ajouter un peu de logique à cela pour lui faire retourner "No File Found"
De cette façon, si la commande précédente a réussi (sortie avec une valeur 0), elle imprimera le fichier actuel, sinon elle affichera "Aucun fichier trouvé"
la source
grep
) plutôt que d'essayer de résoudre le problème en utilisant un meilleur outil (find
) ou en modifiant le paramètre pertinent pour la solution actuelle (avecshopt -s nullglob
)shopt -s nullglob
cela ne fonctionne pas. J'ai essayéfind
en vérifiant ma réponse et elle a échoué. Je pense à cause de l'export dit par Dani.