Проверьте, существует ли каталог в сценарии оболочки - PullRequest
3393 голосов
/ 13 сентября 2008

Какую команду можно использовать для проверки, существует ли каталог в сценарии оболочки?

Ответы [ 34 ]

47 голосов
/ 10 августа 2012

Вот очень прагматичная идиома:

(cd $dir) || return # is this a directory,
                    # and do we have access?

Я обычно заключаю его в функцию:

can_use_as_dir() { 
    (cd ${1:?pathname expected}) || return
}

Или:

assert_dir_access() { 
    (cd ${1:?pathname expected}) || exit
}

Хорошая особенность этого подхода в том, что мне не нужно думать о хорошем сообщении об ошибке.

cd даст мне стандартное однострочное сообщение для stderr. Это также даст больше информации, чем я смогу предоставить. Выполняя cd внутри подоболочки ( ... ), команда не влияет на текущий каталог вызывающей стороны. Если каталог существует, эта подоболочка и функция просто не работают.

Далее следует аргумент, который мы передаем cd: ${1:?pathname expected}. Это более сложная форма замены параметров, которая более подробно описана ниже.

Tl; dr: Если строка, переданная в эту функцию, пуста, мы снова выходим из подоболочки ( ... ) и возвращаемся из функции с данным сообщением об ошибке.


Цитата из справочной страницы ksh93:

${parameter:?word}

Если установлено parameter и не равно нулю, подставьте его значение; в противном случае выведите word и выйдите из оболочки (если он не интерактивный). Если word опущено, печатается стандартное сообщение.

и

Если двоеточие : опущено в приведенных выше выражениях, то shell только проверяет, установлен ли параметр или нет.

Формулировка здесь характерна для документации оболочки, как может означать word на любую разумную строку, включая пробелы.

В данном конкретном случае я знаю, что стандартного сообщения об ошибке 1: parameter not set недостаточно, поэтому я увеличиваю тип ожидаемого здесь значения - pathname каталога.

Философская заметка: Оболочка не является объектно-ориентированным языком, поэтому в сообщении говорится pathname, а не directory. На этом уровне я бы предпочел, чтобы все было просто - аргументы функции - это просто строки.

36 голосов
/ 21 апреля 2010
if [ -d "$Directory" -a -w "$Directory" ]
then
    #Statements
fi

Приведенный выше код проверяет, существует ли каталог и доступен ли он для записи.

25 голосов
/ 05 ноября 2014

Введите этот код в приглашении bash

if [ -d "$DIRECTORY" ]; then
  # if true this block of code will execute
fi
20 голосов
/ 13 сентября 2008

Дополнительные функции, используя find

  • Проверить наличие папки в подкаталогах:

    found=`find -type d -name "myDirectory"`
    if [ -n "$found"]
    then
        # The variable 'found' contains the full path where "myDirectory" is.
        # It may contain several lines if there are several folders named "myDirectory".
    fi
    
  • Проверка существования одной или нескольких папок на основе шаблона в текущем каталоге:

    found=`find -maxdepth 1 -type d -name "my*"`
    if [ -n "$found"]
    then
        # The variable 'found' contains the full path where folders "my*" have been found.
    fi
    
  • Обе комбинации. В следующем примере проверяется наличие папки в текущем каталоге:

    found=`find -maxdepth 1 -type d -name "myDirectory"`
    if [ -n "$found"]
    then
        # The variable 'found' is not empty => "myDirectory"` exists.
    fi
    
19 голосов
/ 17 февраля 2010

На самом деле, вы должны использовать несколько инструментов для пуленепробиваемого подхода:

DIR_PATH=`readlink -f "${the_stuff_you_test}"` # Get rid of symlinks and get abs path
if [[ -d "${DIR_PATH}" ]] ; Then # now you're testing
    echo "It's a dir";
fi

Не нужно беспокоиться о пробелах и специальных символах, пока вы используете "${}".

Обратите внимание, что [[]] не так переносим, ​​как [], но, поскольку большинство людей работают с современными версиями Bash (поскольку, в конце концов, большинство людей даже не работают с командной строкой :-p), преимущество заключается в том, что больше, чем беда.

16 голосов
/ 29 декабря 2015

Для проверки более одного каталога используйте этот код:

if [ -d "$DIRECTORY1" ] && [ -d "$DIRECTORY2" ] then
    # Things to do
fi
16 голосов
/ 07 декабря 2017

Рассматривали ли вы просто делать то, что вы хотите сделать в if, а не смотреть перед тем, как прыгнуть?

IE, если вы хотите проверить наличие каталога перед тем, как его ввести, попробуйте просто сделать это:

if pushd /path/you/want/to/enter; then
    # commands you want to run in this directory
    popd
fi

Если путь, который вы указали для pushd, существует, вы введете его, и он завершится с 0, что означает выполнение части then оператора. Если он не существует, ничего не произойдет (кроме некоторого вывода о том, что каталог не существует, что, вероятно, в любом случае является полезным побочным эффектом для отладки).

Кажется лучше, чем это, что требует повторения:

if [ -d /path/you/want/to/enter ]; then
    pushd /path/you/want/to/enter
    # commands you want to run in this directory
    popd
fi

То же самое работает с cd, mv, rm и т. Д. ... если вы попробуете их на несуществующих файлах, они выйдут с ошибкой и напечатают сообщение о том, что это не t существует, и ваш блок then будет пропущен. Если вы попробуете их на существующих файлах, команда выполнится и выйдет со статусом 0, что позволит выполнить ваш блок then.

15 голосов
/ 23 марта 2016

Проверьте, существует ли каталог, иначе создайте один

[ -d "$DIRECTORY" ] || mkdir $DIRECTORY
14 голосов
/ 19 апреля 2015
[[ -d "$DIR" && ! -L "$DIR" ]] && echo "It's a directory and not a symbolic link"

Примечание: цитирование переменных - это хорошая практика.

12 голосов
/ 19 апреля 2013
[ -d ~/Desktop/TEMPORAL/ ] && echo "DIRECTORY EXISTS" || echo "DIRECTORY DOES NOT EXIST"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...