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
XXXfind
au lieu de la globulation. Il est vraiment plus facile d'utiliserfind
et 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
* .gz
dans le répertoire ou qui ne sont pas des fichiers (doncmkdir a.gz
est pris en compte), les compte, puis teste si le nombre est égal à 0. Si le nombre est égal à 0,xargs test 0 -eq
retournera 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 1
si vous le souhaitez.Vous pouvez supprimer
xargs
avec 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 vaut0
ou1
:[ 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