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).