web-dev-qa-db-fra.com

Rechercher récursivement des 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, quand je lance ce script en terminal, il dit:

[: 29: in: unexpected operator

(avec $extension au lieu de 'in')

Qu'est-ce qui se passe ici, où est l'erreur? Mais cette accolade

370
flip
find $directory -type f -name "*.in"

est un peu plus court que ce tout (et plus sûr - traite des espaces dans les noms de fichiers et noms de répertoires).

Votre script échoue probablement pour les entrées dont le nom ne contient pas ., ce qui rend $extension vide.

658
Mat
find {directory} -type f -name '*.extension'

exemplepour trouver tous les fichiers csv du répertoire courant et de ses sous-répertoires

find . -type f -name '*.csv'
151
Mohammad AlQanneh

La syntaxe que j'utilise est un peu différente de celle suggérée par @Matt:

find $directory -type f -name \*.in

(c'est une frappe de moins).

58
Scott C Wilson

Sans utiliser findname__:

du -a $directory | awk '{print $2}' | grep '\.in$'
12
rtrn
  1. Il manque un { après browsefolders ()
  2. Tous les $in devraient être $suffix
  3. La ligne avec cut ne vous donne que la partie centrale de front.middle.extension. Vous devriez lire votre manuel Shell sur ${varname%%pattern} et ses amis.

Je suppose que vous faites cela comme un exercice de script Shell, sinon la solution find déjà proposée est la voie à suivre.

Pour vérifier la syntaxe du shell, sans exécuter de script, utilisez sh -n scriptname.

10
Jens

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

find . -name 'pom.xml' -print
6
Bharat Yadav

Bien que l’utilisation de la commande find puisse être utile ici, le shell lui-même fournit des options permettant de satisfaire à cette exigence sans outils tiers. Le shell bash fournit une option de prise en charge étendue globale à l'aide de laquelle vous pouvez obtenir les noms de fichiers sous des chemins récursifs correspondant aux extensions souhaitées.

L'option étendue est extglob et doit être définie à l'aide de l'option shopt comme ci-dessous. Les options sont activées avec le support -s et désactivées avec le drapeau -u. En outre, vous pouvez utiliser plusieurs options supplémentaires, à savoir nullglob, dans lesquelles un glob inégalé est entièrement balayé, remplacé par un ensemble de zéro mot. Et globstar qui permet de recurse à travers tous les répertoires

shopt -s extglob nullglob globstar

Il ne vous reste plus qu'à former l'expression globale pour inclure les fichiers d'une certaine extension, ce que vous pouvez faire comme ci-dessous. Nous utilisons un tableau pour renseigner les résultats globaux car, une fois cités correctement et développés, les noms de fichiers avec des caractères spéciaux resteraient intacts et ne seraient pas cassés à cause du fractionnement de Word par le shell.

Par exemple, pour répertorier tous les fichiers *.csv dans les chemins récursifs

fileList=(**/*.csv)

L'option ** permet de recurse à travers les sous-dossiers et *.csv correspond à une expansion globale pour inclure tout fichier des extensions mentionnées. Maintenant, pour imprimer les fichiers réels, faites juste

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

Utiliser un tableau et effectuer une extension citée appropriée est la méthode la plus appropriée dans les scripts Shell, mais pour une utilisation interactive, vous pouvez simplement utiliser ls avec l'expression glob en tant que

ls -1 -- **/*.csv

Cela pourrait très bien être étendu pour correspondre à plusieurs fichiers, c'est-à-dire un fichier se terminant par plusieurs extensions (similaire à l'ajout de plusieurs indicateurs dans la commande find). Par exemple, considérons le cas où il faut obtenir tous les fichiers d’image récursifs, c’est-à-dire avec les extensions *.gif, *.png et *.jpg, c’est tout ce dont vous avez besoin.

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

Cela pourrait très bien être étendu pour avoir des résultats nuls aussi. Avec la même syntaxe, on pourrait utiliser les résultats du glob pour exclure des fichiers d'un certain type. Supposons que vous souhaitiez exclure les noms de fichiers avec les extensions ci-dessus, vous pouvez le faire.

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

La construction !() est une opération de négation visant à ne pas inclure les extensions de fichier répertoriées à l'intérieur et | est un opérateur d'alternance utilisé dans la bibliothèque des expressions régulières étendues pour effectuer une correspondance OR des globs.

Notez que cette prise en charge étendue de glob n'est pas disponible dans POSIX Bourne Shell et qu'elle est purement spécifique aux versions récentes de bash. Donc, si vous envisagez la portabilité des scripts exécutés sur des shells POSIX et bash, cette option ne conviendrait pas.

4
Inian
find $directory -type f -name "*.in"|grep $substring
1
Sergiu
for file in "${LOCATION_VAR}"/*.Zip
do
  echo "$file"
done 
1
find "$PWD" -type f -name "*.in"
1
kip2