J'essaie d'écrire un if
pour tester s'il existe des fichiers correspondant à un certain modèle. S'il y a un fichier texte dans un répertoire, il doit exécuter un script donné.
Mon code actuellement :
if [ -f /*.txt ]; then ./script fi
Veuillez donner quelques idées; Je veux seulement exécuter le script s'il y a un .txt
dans le répertoire.
Réponse acceptée :
[ -f /*.txt ]
renverrait true uniquement s'il y en a un (et un seul) fichier non caché dans /
dont le nom se termine par .txt
et si ce fichier est un fichier normal ou un lien symbolique vers un fichier normal.
C'est parce que les caractères génériques sont développés par le shell avant d'être passés à la commande (ici [
).
Donc s'il y a un /a.txt
et /b.txt
, [
sera passé 5 arguments :[
, -f
, /a.txt
, /b.txt
et ]
. [
se plaindrait alors que -f
reçoit trop d'arguments.
Si vous voulez vérifier que le *.txt
le motif se développe en au moins un fichier non caché (régulier ou non), dans le bash
coque :
shopt -s nullglob
set -- *.txt
if [ "$#" -gt 0 ]; then
./script "[email protected]" # call script with that list of files.
fi
# Or with bash arrays so you can keep the arguments:
files=( *.txt )
# apply C-style boolean on member count
(( ${#files[@]} )) && ./script "${files[@]}"
shopt -s nullglob
est bash
spécifique (shopt
est, nullglob
vient en fait de zsh
), mais des shells comme ksh93
, zsh
, yash
, tcsh
ont des déclarations équivalentes.
Avec zsh
, le test pour existe-t-il des fichiers correspondant à un modèle peut être écrit en utilisant une fonction anonyme et le N
(pour nullglob
) et Y1
(pour s'arrêter après la première recherche) qualificateur global :
if ()(($#)) *.txt(NY1); then
do-something
fi
Notez que ceux-ci trouvent ces fichiers en lisant le contenu du répertoire, il n'essaie pas du tout d'accéder à ces fichiers, ce qui le rend plus efficace que les solutions qui appellent des commandes comme ls
ou stat
sur cette liste de fichiers calculée par le shell.
Le sh
standard l'équivalent serait :
set -- [*].txt *.txt
case "$1$2" in
('[*].txt*.txt') ;;
(*) shift; script "[email protected]"
esac
Le problème est qu'avec les shells Bourne ou POSIX, si un motif ne correspond pas, il s'étend à lui-même. Donc si *.txt
se développe en *.txt
, vous ne savez pas si c'est parce qu'il n'y a pas de .txt
fichier dans le répertoire ou parce qu'il y a un fichier appelé *.txt
. Utilisation de [*].txt *.txt
permet de discriminer entre les deux.
Maintenant, si vous voulez vérifier que le *.txt
correspond à au moins un regular fichier ou lien symbolique vers un fichier normal (comme votre [ -f *.txt ]
vous suggère de faire), ou que tous les fichiers qui correspondent à *.txt
sont réguliers fichiers (après la résolution du lien symbolique), c'est encore une autre affaire.
Avec zsh
:
if ()(($#)) *.txt(NY1-.); then
echo "there is at least one regular .txt file"
fi
if ()(($#)) *.txt(NY1^-.); then
echo "there is at least one non-regular .txt files"
fi
(supprimer le -
si vous voulez faire le test avant la résolution des liens symboliques, c'est-à-dire considérer les liens symboliques comme des fichiers non réguliers, qu'ils pointent vers des fichiers normaux ou non).