Объединение двух отрицательных условий проверки файла (-f и -s), похоже, возвращает неверный результат - PullRequest
1 голос
/ 03 июля 2019

Я хочу проверить, является ли файл файлом и существует ли он и не является ли он пустым, поэтому в итоге использовали комбинированную проверку с -f и -s.Я хочу вернуть сразу, если файл не существует или является пустым, поэтому я отменяю обе проверки.

Чтобы проверить сценарий, в котором мое имя файла вернуло пустую строку, и я передаю путь к каталогу, я пытаюсь это сделать:

if [[ ! -f "/path/to/dir/" ]] && [[ ! -s "/path/to/dir/" ]]; 
then  echo "Does not exists"; else echo "Exists"; fi

Exists

Выше возвращается 'Exist', который кажется неправильным.

-f только проверка правильна:

if [[ ! -f "/path/to/dir/" ]]; then  echo "Does not exists"; 
else echo "Exists"; fi

Не существует

Комбинированная проверка, но без отрицания каждого, также правильна:

if [[ -f "/path/to/dir/" ]] && [[ -s "/path/to/dir/" ]]; 
then  echo "Exists"; else echo "Does not exists"; fi

Не существует

Не уверен, что я делаю что-то не так или есть какая-то странностьв Bash при объединении отрицательных условий с логическими и &&?

Правка 1: как и в случае с нотацией, где оба условия находятся в одном наборе скобок:

if [[ ! -f "/opt/gmdemea/smartmap_V2/maps/" && ! -s "/opt/gmdemea/smartmap_V2/maps/" ]]; then  echo "Does not exists"; else echo "Exists"; fi

Существует

Но это не меняет поведения.

Редактировать 2: Из справочной страницы кажется, что в этой ситуации -s должно быть достаточно, но при прохождении существующего пути к каталогу возвращаетсяtrue (версия Bash: 4.1.2 (1) -релиз):

if [[ -s "/opt/gmdemea/smartmap_V2/maps/" ]]; then echo "Exists"; else echo "Does not exists"; fi 

Exists

Возвращает «Exists», пока это не файл, поэтому следует обратиться к предложению else, возвращающему «Not существует»

Ответы [ 2 ]

4 голосов
/ 03 июля 2019

@ KamilCuk уже объяснил недостаток логики, но в целом - всегда избегайте использования негативов в вашем коде, например. ! в этом случае, поскольку они затрудняют чтение кода (и получают правильные результаты), чем использование положительных значений. Вместо:

if [[ ! -f "/path/to/dir/" ]] && [[ ! -s "/path/to/dir" ]]
then
    echo "Does not exists"
else
    echo "Exists"
fi

если бы вы применили булеву алгебру для выделения ! s, то вы получите:

if ! ( [[ -f "/path/to/dir/" ]] || [[ -s "/path/to/dir" ]] )
then
    echo "Does not exists"
else
    echo "Exists"
fi

, который вы можете затем перевернуть в if / else, чтобы избавиться от финала !:

if [[ -f "/path/to/dir/" ]] || [[ -s "/path/to/dir" ]]
then
    echo "Exists"
else
    echo "Does not exists"
fi

, который вы можете сразу увидеть сразу, - это не тот тест, который вы пытались выполнить. Вместо этого вы бы хотели:

if [[ -f "/path/to/dir/" ]] && [[ -s "/path/to/dir" ]]
then
    echo "Exists"
else
    echo "Does not exists"
fi
4 голосов
/ 03 июля 2019

Имея x AND y, а затем преграждая его, вы получаете: NOT (x AND y). Это равно (NOT a) OR (NOT b). не равно (NOT x) AND (NOT y).

Я хочу проверить, существует ли файл и существует ли он и не является ли он пустым

Если вы хотите проверить, является ли файл обычным файлом и не является ли он пустым, выполните:

[[ -f path ]] && [[ -s path ]]

Отрицание будет (каждая строка равна) (примечание Закон де Моргана ):

! ( [[ -f path ]] && [[ -s path ]] )
[[ ! -f path || ! -s path ]]

Который вы можете написать также как (каждая строка равна):

! [[ -f path && -s path ]]
[[ ! ( -f path && -s path ) ]]
[[ ! -f path ]] || [[ ! -s path ]]
# or using `[` test and `-a` and `-o`:
! [ -f path -a -s path ]
[ ! -f path -o ! -s path ]
[ ! \( -f path -a -s path \) ]

Так просто:

if [[ ! -f "/path/to/dir/" || ! -s "/path/to/dir/" ]]; then
     echo "The /path/to/dir is not a regular file or size is nonzero"
else
     echo "The path /path/to/dir is a regular file and it's size is zero"
fi
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...