1
votes

Bash: vérifiez si un répertoire contient uniquement des fichiers avec un suffixe spécifique

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


0 commentaires

4 Réponses :


1
votes

Je veux vérifier si / my / dir / contient uniquement des fichiers * .gz et rien d'autre.

Utilisez find au lieu de la globulation. Il est vraiment plus facile d'utiliser find 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'utiliser find :

XXX

Ceci trouve toutes les "choses" qui ne sont pas nommées * .gz dans le répertoire ou qui ne sont pas des fichiers (donc mkdir 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 entre 1 - 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 de test , qui vaut 0 ou 1:

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


1 commentaires

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



1
votes

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'


0 commentaires

1
votes

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


0 commentaires

1
votes

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


3 commentaires

-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