509 votes

Recherche récursive de fichiers avec une extension spécifique

J'essaie de trouver tous les fichiers avec une extension spécifique dans un répertoire et ses sous-répertoires avec mon bash (dernière version Ubuntu LTS).

C'est ce qui est écrit dans un fichier script :

#!/bin/bash

directory="/home/flip/Desktop"
suffix="in"

browsefolders ()
  for i in "$1"/*; 
  do
    echo "dir :$directory"
    echo "filename: $i"
    #   echo ${i#*.}
    extension=`echo "$i" | cut -d'.' -f2`
    echo "Erweiterung $extension"
    if     [ -f "$i" ]; then        

        if [ $extension == $suffix ]; then
            echo "$i ends with $in"

        else
            echo "$i does NOT end with $in"
        fi
    elif [ -d "$i" ]; then  
    browsefolders "$i"
    fi
  done
}
browsefolders  "$directory"

Malheureusement, lorsque je lance ce script dans le terminal, le message suivant apparaît :

[: 29: in: unexpected operator

(avec $extension au lieu de 'in' )

Que se passe-t-il ici, où est l'erreur ? Mais cette accolade

2 votes

L'erreur provient d'un "{" manquant

10voto

Inian Points 36223

Bien que l'utilisation de find peut être utile ici, l'interpréteur de commandes fournit lui-même des options permettant de répondre à cette exigence sans avoir recours à des outils tiers. La commande bash fournit une option de prise en charge étendue des globes qui vous permet d'obtenir les noms de fichiers sous les chemins récursifs qui correspondent aux extensions que vous souhaitez.

L'option étendue est extglob qui doit être défini à l'aide de la fonction shopt comme indiqué ci-dessous. Les options sont activées à l'aide de la touche -s et handicapés avec l'aide de l -u drapeau. En outre, vous pouvez utiliser quelques options supplémentaires, à savoir nullglob dans lequel un glob non apparié est entièrement balayé et remplacé par un ensemble de mots nuls. Et globstar qui permet de parcourir tous les répertoires

shopt -s extglob nullglob globstar

Il ne vous reste plus qu'à formuler l'expression globale pour inclure les fichiers d'une certaine extension, ce que vous pouvez faire comme suit. Nous utilisons un tableau pour remplir les résultats de l'expression globale car, lorsqu'elle est citée correctement et développée, les noms de fichiers contenant des caractères spéciaux restent intacts et ne sont pas interrompus par le découpage des mots effectué par l'interpréteur de commandes.

Par exemple, pour dresser la liste de tous les *.csv les fichiers dans les chemins récursifs

fileList=(**/*.csv)

L'option ** est de parcourir les sous-dossiers et les *.csv est une expansion globale permettant d'inclure n'importe quel fichier des extensions mentionnées. Pour imprimer les fichiers, il suffit de faire

printf '%s\n' "${fileList[@]}"

L'utilisation d'un tableau et d'une expansion entre guillemets appropriée est la bonne méthode lorsqu'elle est utilisée dans des scripts de l'interpréteur de commandes, mais pour une utilisation interactive, vous pouvez simplement utiliser ls avec l'expression globale comme

ls -1 -- **/*.csv

Cela pourrait très bien être étendu pour correspondre à des fichiers multiples, c'est-à-dire des fichiers se terminant par des extensions multiples (similaire à l'ajout de drapeaux multiples dans la fonction find commande). Prenons par exemple le cas où il faut récupérer tous les fichiers images récursifs, c'est-à-dire d'extension *.gif , *.png y *.jpg Il suffit de

ls -1 -- **/+(*.jpg|*.gif|*.png)

Il pourrait très bien être étendu pour obtenir des résultats négatifs également. Avec la même syntaxe, on pourrait utiliser les résultats du glob pour exclure des fichiers d'un certain type. Supposons que vous vouliez exclure les noms de fichiers avec les extensions ci-dessus, vous pourriez faire

excludeResults=()
excludeResults=(**/!(*.jpg|*.gif|*.png))
printf '%s\n' "${excludeResults[@]}"

La construction !() est une opération de négation permettant de n'inclure aucune des extensions de fichiers énumérées à l'intérieur et | est un opérateur d'alternance tel qu'il est utilisé dans la bibliothèque d'expressions régulières étendues pour effectuer une correspondance OR des globes.

Notez que ce support étendu des globes n'est pas disponible dans l'interpréteur de commandes bourne POSIX et qu'il est purement spécifique aux versions récentes de bash . Ainsi, si vous envisagez la portabilité des scripts fonctionnant sous POSIX et bash coquilles, cette option ne conviendrait pas.

10voto

Jens Points 17702
  1. Il y a un { manquant après browsefolders ()
  2. Tous $in devrait être $suffix
  3. La ligne avec cut ne permet d'obtenir que la partie centrale de front.middle.extension . Vous devriez lire votre manuel de l'interpréteur de commandes sur ${varname%%pattern} et ses amis.

Je suppose que vous faites cela comme un exercice de script shell, sinon l'option find La solution déjà proposée est la bonne.

Pour vérifier que la syntaxe de l'interpréteur de commandes est correcte, sans exécuter un script, utilisez la commande sh -n scriptname .

7voto

Bharat Yadav Points 69

Pour trouver tous les pom.xml dans votre répertoire actuel et les imprimer, vous pouvez utiliser :

find . -name 'pom.xml' -print

1voto

Sergiu Points 11
find $directory -type f -name "*.in"|grep $substring

1voto

for file in "${LOCATION_VAR}"/*.zip
do
  echo "$file"
done

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X