Как выйти из оболочки script, если целевой файл не существует - программирование
Подтвердить что ты не робот

Как выйти из оболочки script, если целевой файл не существует

Учитывая script ниже, я хотел бы избежать выполнения конвейера, если файл не существует.

Как я могу выйти из script сразу, если файл txt не найден?

ls */*.txt | grep ab1 | awk '{print $1, $1}' | sed "s/\"/\"\"/g" | xargs -L1 mv
4b9b3361

Ответ 1

Вы можете проверить наличие файла с чем-то вроде:

if [[ -f x.txt ]] ; then
    echo file exists.
fi

Чтобы выйти, если этого не произойдет, достаточно:

if [[ ! -f x.txt ]] ; then
    echo 'File "x.txt" is not there, aborting.'
    exit
fi

-f <file> - это только одно из многих условных выражений, которые вы можете использовать. Если вы посмотрите на bash man-страницу в разделе CONDITIONAL EXPRESSIONS, вы увидите весь их массив.


Если (как указано в обновлении вопроса) вы хотите проверить, приводит ли подстановочный знак к файлам, вы можете просто расширить его, отбросив ошибки. Если их нет, вы получите пустую строку, которая может быть обнаружена с помощью -z:

if [[ -z "$(ls -1 */*.txt 2>/dev/null | grep ab1)" ]] ; then
    echo 'There are no "*/*.txt" files.'
    exit
fi

Обратите внимание, что я использовал -1 для принудительного создания одного файла на строку, хотя Linux ls делает это по умолчанию, если устройство вывода не является терминалом (из памяти). Это на всякий случай, если вы попробуете это на машине, которая в этом случае не будет заставлять одну строку.


Имейте в виду, что если у вас есть пробелы в именах файлов, использование ls и затем awk для извлечения столбца 1 не будет работать слишком хорошо. Например, файл abc ab1.txt приведет к извлечению только бит abc.

Использование find с -print0, в сочетании с xargs с -0 является обычным способом правильной обработки файлов, которые могут иметь в них "специальные" символы. Существует много других опций, которые вы можете предоставить find для обеспечения обработки только необходимых файлов, таких как -maxdepth, чтобы ограничить скорость перемещения по дереву каталогов и -name, чтобы правильно фильтровать имена файлов.

Однако, если вы знаете, что у вас никогда не будет таких типов файлов, вероятно, хорошо использовать решение ls, просто убедитесь, что вам комфортно с его недостатками.

Ответ 2

Используйте test

Быстрый и короткий способ тестирования на существование:

test -e $FILENAME || exit

Вы можете связать его, выполнив:

test -e $FILENAME && something | something-else 

В этом случае something и something-else будут выполняться только в том случае, если файл существует.

Например:

➤ test -e ~/.bashrc && echo True || echo False
True
➤ test -e ./exists-not && echo True || echo False
False

Кроме того: Обратите внимание, что [ является псевдонимом для test. Семантика [[ определяется bash и может быть найдена в bash manpage

Однако...

... вам, вероятно, лучше использовать find для получения ваших файлов:

find ./ -maxdepth 2 -name "*ab1*.txt" -exec do-something-to-filename '{}' \;

Поскольку вывод ls не может быть надежно проанализирован. Это также будет выполнять только команду do-something-to-filename, если имя файла существует, что, как я думаю, вы пытаетесь сделать.

{} будет заменен именем файла для каждого вызова do-something-to-filename.

Ответ 3

find ... -exec ... или find ... -print0 | xargs -0 ..., как правило, отлично, но вы можете сделать это напрямую с помощью glob с помощью опции bash nullglob:

bash-3.2$ echo *foo
*foo
bash-3.2$ shopt -s nullglob
bash-3.2$ echo *foo

bash-3.2$ 

В зависимости от остальной части вашего script, вы можете или не захотите повторно установить его с помощью shopt -u nullglob.

Ответ 4

Я пробовал это, и это сработало для меня

test -s <<your file path>> && exit 0 || <<things to do when file NOT exists>>

Обратите внимание, что я действительно выхожу, когда файл отсутствует