333 votes

Teste si un glob a des correspondances dans bash

Si je veux vérifier l'existence d'un seul fichier, je peux le tester à l'aide d' test -e filename ou [ -e filename ].

En supposant que j'ai une boule et je veux savoir si il existe des fichiers dont les noms correspondent au glob. Le glob peuvent correspondre à des fichiers 0 (dans ce cas, j'ai besoin de ne rien faire), ou il peut correspondre à 1 ou plusieurs fichiers (dans ce cas, j'ai besoin de faire quelque chose). Comment puis-je vérifier si un glob a tout les matchs? (Je ne m'inquiète pas combien de matches il y a, et il serait mieux si je pouvais le faire avec un if déclaration et aucune boucle (tout simplement parce que je trouve que la plus lisible).

(test -e glob* échoue si le glob correspond à plus d'un fichier.)

215voto

flabdablet Points 1066

Le nullglob option shell est en effet un bashism.

Pour éviter la nécessité d'un fastidieux d'enregistrer et de restaurer des nullglob état, j'avais mis à l'intérieur de la shell interne est exécuté, ce qui élargit le glob:

if test -n "$(shopt -s nullglob; echo glob*)"
then
    echo found
else
    echo not found
fi

Pour une meilleure portabilité et plus souple d'expansion, utilisez trouver:

if test -n "$(find . -maxdepth 1 -name 'glob*' -print -quit)"
then
    echo found
else
    echo not found
fi

Explicite -l'impression de quitter des actions sont utilisés pour trouver au lieu de la valeur par défaut implicite -de l'impression de l'action, de sorte que trouver va quitter dès qu'il trouve le premier fichier correspondant aux critères de recherche. D'où le grand nombre de fichiers de match, cela devrait fonctionner beaucoup plus rapidement qu' echo glob* ou ls glob* et il évite également la possibilité d'une contrainte l'élargissement de la ligne de commande (quelques coquilles ont un 4K limite de longueur).

Si trouver se sent comme exagéré, et le nombre de fichiers susceptibles de match est petite, utilisez stat:

if stat -t glob* >/dev/null 2>&1
then
    echo found
else
    echo not found
fi

33voto

Dan Bloch Points 61

J'aime

 exists() {
    [ -e "$1" ]
}

if exists glob*; then
    echo found
else
    echo not found
fi
 

C’est à la fois lisible et efficace (sauf s’il existe un grand nombre de fichiers). Le principal inconvénient est que c'est beaucoup plus subtil qu'il n'y paraît, et je me sens parfois obligé d'ajouter un long commentaire. S'il existe une correspondance, "glob *" est développé par le shell et toutes les correspondances sont passées à exist (), qui vérifie la première et ignore le reste. S'il n'y a pas de correspondance, "glob *" est passé à exist () et n'est pas non plus présent.

27voto

miku Points 63392
#!/usr/bin/env bash

# If it is set, then an unmatched glob is swept away entirely -- 
# replaced with a set of zero words -- 
# instead of remaining in place as a single word.
shopt -s nullglob

M=(*px)

if [ "${#M[*]}" -ge 1 ]; then
    echo "${#M[*]} matches."
else
    echo "No such files."
fi

15voto

James Andino Points 3272

Si vous avez globfail réglé, vous pouvez utiliser ce fou (ce que vous ne devriez vraiment pas faire)

 shopt -s failglob # exit if * does not match 
( : * ) && echo 0 || echo 1
 

ou

 q=( * ) && echo 0 || echo 1
 

8voto

user2969675 Points 41

test -e a la mise en garde malheureuse selon laquelle il considère que les liens symboliques brisés n'existent pas. Donc, vous voudrez peut-être vérifier pour ceux-là aussi.

 function globexists {
  test -e "$1" -o -L "$1"
}

if globexists glob*; then
    echo found
else
    echo not found
fi
 

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