bash: убедитесь, что каталог содержит только файлы с определенным суффиксом - PullRequest
1 голос
/ 03 апреля 2019

Я пытаюсь написать скрипт, который будет проверять, содержит ли каталог только определенный тип файла (и / или папки) и вернет 1 для false, 0 для true.

IE: я хочу проверить, содержит ли / my / dir / только файлы * .gz и ничего больше.

Это то, что у меня есть, но, похоже, оно не работает так, как задумано:

# 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 ]

2 голосов
/ 03 апреля 2019

Использование Bash's extglob, !(*.gz) и grep:

$ if grep -qs . path/!(*.gz) ; then echo yes ; else echo nope ; fi

man 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.
1 голос
/ 03 апреля 2019

Некоторые предлагают подсчитать все файлы, которые не соответствуют шаблону сглаживания *.gz.Это может быть довольно неэффективно в зависимости от количества файлов.Для вашей работы достаточно найти только один файл, который не соответствует вашему шаблону.Используйте действие -quite find для выхода после первого матча:

if [ -z "$(find /usr/share/man/man1/* -not -name '*.gz' -print -quit)" ]
then echo only gz
fi
1 голос
/ 03 апреля 2019

Поскольку вы используете bash, вы можете использовать другую настройку: 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'

1 голос
/ 03 апреля 2019

Я хочу проверить, содержит ли / my / dir / файлы * .gz и ничего больше.

Используйте find вместо глобуляции. На самом деле проще использовать find и анализировать результаты поиска. Глобализация проста для простых сценариев, но как только вы захотите проанализировать «все файлы в каталоге» и выполнить некоторую фильтрацию и тому подобное, гораздо проще (и безопаснее) использовать find:

find "$1" -mindepth 1 -maxdepth 1 \! -name '*.gz' -o \! -type f | wc -l | xargs test 0 -eq

Это находит все «вещи», которые не имеют названия *.gz внутри каталога или не являются файлами (поэтому учитывается mkdir a.gz), подсчитывает их, а затем проверяет, равно ли их количество 0. Если число равно 0, xargs test 0 -eq вернет 0, если нет, то вернет статус между 1 - 125. Вы можете обработать ненулевой статус возврата простым || return 1, если хотите.

Вы можете удалить xargs с помощью простой подстановки bash и использовать метод из this thread для небольшого ускорения и получить test возвращаемое значение, равное 0 или 1:

[ 0 -eq "$(find "$1" -mindepth 1 -maxdepth 1 \! -name '*.gz' -o \! -type f -print '.' | wc -c)" ]

Помните, что статус выхода скрипта - это статус выхода последней выполненной команды. Так что вам больше ничего не нужно в вашем сценарии, если хотите, только шебанга и этого единственного лайнера будет достаточно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...