web-dev-qa-db-fra.com

Boucle à travers tous les fichiers avec une extension spécifique

for i in $(ls);do
    if [ $i = '*.Java' ];then
        echo "I do something with the file $i"
    fi
done

Je veux parcourir chaque fichier du dossier actuel et vérifier s'il correspond à une extension spécifique. Le code ci-dessus ne fonctionne pas, savez-vous pourquoi?

95
AR89

Aucune astuce de fantaisie nécessaire:

for i in *.Java; do
    [ -f "$i" ] || break
    ...
done

Le gardien veille à ce que, s’il n’ya pas de fichiers correspondants, la boucle se ferme sans essayer de traiter un nom de fichier inexistant *.Java. Dans bash (ou des shells supportant quelque chose de similaire), vous pouvez utiliser l'option nullglob pour simplement ignorer une correspondance ayant échoué et ne pas entrer dans le corps de la boucle.

shopt -s nullglob
for i in *.Java; do
    ...
done
174
chepner

la réponse correcte est @ chepner

EXT=Java
for i in *.${EXT}; do
    ...
done

cependant, voici un petit truc pour vérifier si un nom de fichier a une extension donnée:

EXT=Java
for i in *; do
    if [ "${i}" != "${i%.${EXT}}" ];then
        echo "I do something with the file $i"
    fi
done
13
umläute

Ajouter récursivement des sous-dossiers,

for i in `find . -name "*.Java" -type f`; do
    echo "$i"
done
9
luismartingil

Boucle à travers tous les fichiers se terminant par: .img, .bin, .txt suffixe et affiche le nom du fichier:

for i in *.img *.bin *.txt;
do
  echo "$i"
done

Ou de manière récursive (trouver également dans tous les sous-répertoires):

for i in `find . -type f -name "*.img" -o -name "*.bin" -o -name "*.txt"`;
do
  echo "$i"
done
3
Benny

comme @chepner dit dans son commentaire, vous comparez $ i à une chaîne fixe.

Pour développer et rectifier la situation, vous devez utiliser [[]] avec l'opérateur regex = ~

par exemple:

for i in $(ls);do
    if [[ $i =~ .*\.Java$ ]];then
        echo "I want to do something with the file $i"
    fi
done

l'expression régulière à droite de = ~ est testée par rapport à la valeur de l'opérateur de gauche et ne doit pas être citée, (quoted ne provoquera pas d'erreur, mais sera comparée à une chaîne fixe et échouera donc très probablement "

mais la réponse de @chepner ci-dessus en utilisant glob est un mécanisme beaucoup plus efficace.

2
peteches

Je suis d’accord avec les autres réponses concernant la bonne façon de parcourir les fichiers. Cependant, le PO a demandé:

Le code ci-dessus ne fonctionne pas, savez-vous pourquoi?

Oui!

Un excellent article Quelle est la différence entre test, [et [[?]) explique en détail qu'entre autres différences, vous ne pouvez pas utiliser expression matching ou pattern matching dans la commande test (qui est un raccourci pour [)

 
 Nouveau test [[ancien test [Exemple 
 
 Correspondance de motif = (ou ==) (non disponible) [[$ name = a *]] || echo "nom ne commence pas par un 'a': $ nom" 
 
 Expression rationnelle = ~ (non disponible) [[$ (date) = ~ ^ ven\...\13] ] && echo "C'est vendredi le 13!" 
 correspondant à 

C'est donc la raison pour laquelle votre script a échoué. Si le PO est intéressé par une réponse avec le [[ _ syntaxe (qui a l’inconvénient de ne pas être supportée par autant de plates-formes que la [ commande), je serais heureux de modifier ma réponse pour l’inclure.

EDIT: Tout commentaire sur la manière de formater les données dans la réponse sous forme de tableau serait utile!

2
user000001