J'essaie d'écrire un script qui vérifiera si un répertoire contient uniquement un type spécifique de fichier (et / ou dossier) et renverra 1 pour faux, 0 pour vrai.
IE: Je veux vérifier si / my / dir / contient uniquement * Fichiers .gz et rien d'autre.
Voici ce que j'ai jusqu'à présent, mais cela ne semble pas fonctionner comme prévu:
# Basic vars
readonly THIS_JOB=${0##*/}
readonly ARGS_NBR=1
declare dir_in=$1
dir_in=$1"/*.gz"
#echo $dir_in
files=$(shopt -s nullglob dotglob; echo ! $dir_in)
echo $files
if (( ${#files} ))
then
echo "Success: Directory contains files."
exit 0
else
echo "Failure: Directory is empty (or does not exist or is a file)"
exit 1
fi
4 Réponses :
Je veux vérifier si / my / dir / contient uniquement des fichiers * .gz et rien d'autre.
Utilisez
XXXfindau lieu de la globulation. Il est vraiment plus facile d'utiliserfindet d'analyser la sortie de recherche. La globulation est simple pour les scripts simples, mais une fois que vous voulez analyser "tous les fichiers d'un répertoire" et faire un peu de filtrage et autres, il est beaucoup plus facile (et plus sûr) d'utiliserfind:Ceci trouve toutes les "choses" qui ne sont pas nommées
* .gzdans le répertoire ou qui ne sont pas des fichiers (doncmkdir a.gzest pris en compte), les compte, puis teste si le nombre est égal à 0. Si le nombre est égal à 0,xargs test 0 -eqretournera 0, sinon, il sera retourne l'état entre1 - 125. Vous pouvez gérer le statut de retour différent de zéro avec un simple|| renvoyez 1si vous le souhaitez.Vous pouvez supprimer
xargsavec une simple substitution bash et utiliser la méthode de ce fil de discussion pour accélérer un peu et obtenir la valeur de retour detest, qui vaut0ou1:[ 0 -eq "$(find "$1" -mindepth 1 -maxdepth 1 \! -name '*.gz' -o \! -type f -print '.' | wc -c)" ]N'oubliez pas que l'état de sortie d'un script est l'état de sortie de la dernière commande réalisé. Donc, vous n'avez besoin de rien d'autre dans votre script si vous le souhaitez, seul un shebang et cet oneliner suffiront.
vous n'êtes pas sûr de pouvoir garantir que xargs renverra 123 (freebsd renvoie 1) mais devrait certainement être une valeur entre 1..125
Puisque vous utilisez bash, vous pouvez utiliser un autre paramètre: GLOBIGNORE
#!/bin/bash
containsonly(){
dir="$1"
glob="$2"
if [ ! -d "$dir" ]; then
echo 1>&2 "Failure: directory does not exist"
return 2
fi
local res=$(
cd "$dir"
GLOBIGNORE=$glob"
shopt -s nullglob dotglob
echo *
)
if [ ${#res} = 0 ]; then
echo 1>&2 "Success: directory contains no extra files"
return 0
else
echo 1>&2 "Failure: directory contains extra files"
return 1
fi
}
# ...
containsonly myfolder '*.gz'
Utilisation de extglob de Bash, ! (*. gz) et grep:
-q, --quiet, --silent
Quiet; do not write anything to standard output. Exit
immediately with zero status if any match is found, even if an
error was detected. Also see the -s or --no-messages option.
-s, --no-messages
Suppress error messages about nonexistent or unreadable files.
man grep :
$ if grep -qs . path/!(*.gz) ; then echo yes ; else echo nope ; fi
Certains ont suggéré de compter tous les fichiers qui ne correspondent pas au modèle de globbing * .gz . Cela peut être assez inefficace selon le nombre de fichiers. Pour votre travail, il suffit de trouver un seul fichier, qui ne correspond pas à votre modèle de globbing. Utilisez l'action -quite de find pour quitter après la première correspondance:
if [ -z "$(find /usr/share/man/man1/* -not -name '*.gz' -print -quit)" ] then echo only gz fi
-not et -quit ne sont pas compatibles POSIX, je pense. -not peut simplement être remplacé par ! mais -quit n'existe pas dans busybox par exemple. Dans ce cas, puisque nous avons bash, je suppose qu'il pourrait être remplacé par quelque chose comme -exec bash -c 'kill -PIPE $ PPID' \; (ou simplement find ... | head -n 1 )
@jhnc quelqu'un qui utilise un outil GNU, le Bash, utilise probablement aussi les autres outils GNU et ne se soucie pas de la conformité POSIX.
J'utilise bash sur freebsd mais de nombreux utilitaires ne sont pas GNU