Проверьте, существует ли каталог в сценарии оболочки

StackOverflow https://stackoverflow.com/questions/59838

  •  09-06-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение

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

if [ -d "$DIRECTORY" ]; then
  # Control will enter here if $DIRECTORY exists.
fi

Или проверить, не существует ли каталог:

if [ ! -d "$DIRECTORY" ]; then
  # Control will enter here if $DIRECTORY doesn't exist.
fi

Однако, как Джон Эриксон указывает, что последующие команды могут работать не так, как задумано, если не принять во внимание, что символическая ссылка на каталог также пройдет эту проверку.Например.запускаю это:

ln -s "$ACTUAL_DIR" "$SYMLINK"
if [ -d "$SYMLINK" ]; then 
  rmdir "$SYMLINK" 
fi

Выдаст сообщение об ошибке:

rmdir: failed to remove `symlink': Not a directory

Поэтому символические ссылки, возможно, придется обрабатывать по-другому, если последующие команды ожидают каталоги:

if [ -d "$LINK_OR_DIR" ]; then 
  if [ -L "$LINK_OR_DIR" ]; then
    # It is a symlink!
    # Symbolic link specific commands go here.
    rm "$LINK_OR_DIR"
  else
    # It's a directory!
    # Directory command goes here.
    rmdir "$LINK_OR_DIR"
  fi
fi

Обратите особое внимание на двойные кавычки, используемые для переноса переменных, причину этого объясняет 8jean. в другом ответе.

Если переменные содержат пробелы или другие необычные символы, это, вероятно, приведет к сбою сценария.

Другие советы

Не забудьте всегда обернуть переменные в двойные цитаты при ссылке на их сценарий.В наши дни дети растут с мыслью, что в именах их каталогов могут быть пробелы и множество других забавных символов.(Пробелы!В мои времена у нас не было шикарных помещений!;))

Однажды один из этих детей запустит ваш сценарий с помощью $DIRECTORY установлен в "My M0viez" и ваш сценарий взорвется.Вы этого не хотите.Так что используйте это.

if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists, even if it contains spaces
fi

Обратите внимание тест может дать некоторые удивительные результаты:

$ ln -s tmp/ t
$ if [ -d t ]; then rmdir t; fi
rmdir: directory "t": Path component not a directory

Файл в папке:"Когда каталог не каталог?" Ответ:«Когда это символизирует каталог». Немного более тщательный тест:

if [ -d t ]; then 
   if [ -L t ]; then 
      rm t
   else 
      rmdir t
   fi
fi

Дополнительную информацию можно найти в руководстве Bash на странице Условные выражения Bash и [ встроенная команда и [[ составная команда.

Я нахожу двойная скобка версия test делает написание логических тестов более естественным:

if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
    echo "It's a bona-fide directory"
fi

Более короткая форма:

[ -d "$DIR" ] && echo "Yes"

Чтобы проверить, существует ли каталог, вы можете использовать простую структуру if, подобную этой:

if [ -d directory/path to a directory ] ; then
#Things to do

else #if needed #also: elif [new condition] 
# things to do
fi

Вы можете сделать это также в отрицательном

if [ ! -d directory/path to a directory ] ; then
# things to do when not an existing directory

Примечание:Будьте осторожны, оставляйте пустые места по обе стороны от открывающих и закрывающих скобок.

С тем же синтаксисом вы можете использовать:

-e: any kind of archive 

-f: file 

-h: symbolic link 

-r: readable file 

-w: writable file 

-x: executable file 

-s: file size greater than zero 
if [ -d "$DIRECTORY" ]; then  
    # Here if $DIRECTORY exists  
fi

Вы можете использовать test -d (видеть man test).

-d file Истинно, если файл существует и является каталогом.

Например:

test -d "/etc" && echo Exists || echo Does not exist

Примечание:А test команда аналогична условному выражению [ (видеть: man [), поэтому его можно переносить в сценарии оболочки.

[ - это синоним слова test встроенный, но последний аргумент должен быть буквальным ], чтобы соответствовать открытию [.

Для возможных вариантов или дополнительной помощи проверьте:

  • help [
  • help test
  • man test или man [
  1. Простой скрипт для проверки наличия каталога или файла:

    if [ -d /home/ram/dir ]   # for file "if [-f /home/rama/file]" 
    then 
        echo "dir present"
    else
        echo "dir not present"
    fi
    
  2. Простой скрипт для проверки наличия каталога:

    mkdir tempdir   # if you want to check file use touch instead of mkdir
    ret=$?
    if [ "$ret" == "0" ]
    then
        echo "dir present"
    else
        echo "dir not present"
    fi
    

    Приведенные выше сценарии проверят наличие каталога или его отсутствие.

    $? если последняя команда выполнена успешно, она возвращает «0», иначе ненулевое значение.предполагать tempdir тогда уже присутствует mkdir tempdir выдаст ошибку, как показано ниже:

    мкдир:невозможно создать каталог «tempdir»:Файл существует

Или за что-то совершенно бесполезное:

[ -d . ] || echo "No"

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

(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}.Это более сложная форма подстановки параметров, которая более подробно объясняется ниже.

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


Цитирую из ksh93 справочная страница:

${parameter:?word}

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

и

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

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

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

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

if [ -d "$Directory" -a -w "$Directory" ]
then
    #Statements
fi

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

Введите этот код в командной строке bash

if [ -d "$DIRECTORY" ]; then
  # if true this block of code will execute
fi

Больше возможностей с помощью 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
    

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

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), то пользы больше, чем проблем.

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

if [ -d "$DIRECTORY1" ] && [ -d "$DIRECTORY2" ] then
    # Things to do
fi

Рассматривали ли вы возможность просто делать все, что хотите, в 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, и т. д...если вы попробуете их с файлами, которые не существуют, они выйдут с ошибкой и напечатают сообщение о том, что их не существует, и ваш then блок будет пропущен.Если вы попробуете их на существующих файлах, команда выполнится и завершится со статусом 0, позволяя вашему then блок для выполнения.

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

[ -d "$DIRECTORY" ] || mkdir $DIRECTORY
[[ -d "$DIR" && ! -L "$DIR" ]] && echo "It's a directory and not a symbolic link"

Примечание:Заключение переменных в кавычки — хорошая практика.

[ -d ~/Desktop/TEMPORAL/ ] && echo "DIRECTORY EXISTS" || echo "DIRECTORY DOES NOT EXIST"

Этот ответ завернутый в виде сценария оболочки

Примеры

$ is_dir ~                           
YES

$ is_dir /tmp                        
YES

$ is_dir ~/bin                       
YES

$ mkdir '/tmp/test me'

$ is_dir '/tmp/test me'
YES

$ is_dir /asdf/asdf                  
NO

# Example of calling it in another script
DIR=~/mydata
if [ $(is_dir $DIR) == "NO" ]
then
  echo "Folder doesnt exist: $DIR";
  exit;
fi

is_dir

function show_help()
{
  IT=$(CAT <<EOF

  usage: DIR
  output: YES or NO, depending on whether or not the directory exists.

  )
  echo "$IT"
  exit
}

if [ "$1" == "help" ]
then
  show_help
fi
if [ -z "$1" ]
then
  show_help
fi

DIR=$1
if [ -d $DIR ]; then 
   echo "YES";
   exit;
fi
echo "NO";

Используя -e check проверит наличие файлов, включая каталоги.

if [ -e ${FILE_PATH_AND_NAME} ]
then
    echo "The file or directory exists."
fi

Согласно Джонатан комментарий:

Если вы хотите создать каталог, а он еще не существует, то самый простой способ — использовать mkdir -p который создает каталог — и все недостающие каталоги по пути — и не дает сбоя, если каталог уже существует, поэтому вы можете сделать все это сразу с помощью:

mkdir -p /some/directory/you/want/to/exist || exit 1
if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists
fi

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

Поэтому:

if [ -d "$DIRECTORY" ] && [ -x "$DIRECTORY" ] ; then
    # ... to go to that directory (even if DIRECTORY is a link)
    cd $DIRECTORY
    pwd
fi

if [ -d "$DIRECTORY" ] && [ -w "$DIRECTORY" ] ; then
    # ... to go to that directory and write something there (even if DIRECTORY is a link)
    cd $DIRECTORY
    touch foobar
fi

А ls команда в сочетании с -l (длинный список) возвращает информацию об атрибутах файлов и каталогов.
В частности первый персонаж ls -l вывод, это обычно d или - (бросаться).В случае d тот, что указан, наверняка является каталогом.

Следующая команда всего в одной строке сообщит вам, задано ли данное ISDIR переменная содержит путь к каталогу или нет:

[[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] &&
    echo "YES, $ISDIR is a directory." || 
    echo "Sorry, $ISDIR is not a directory"

Практическое использование:

    [claudio@nowhere ~]$ ISDIR="$HOME/Music" 
    [claudio@nowhere ~]$ ls -ld "$ISDIR"
    drwxr-xr-x. 2 claudio claudio 4096 Aug 23 00:02 /home/claudio/Music
    [claudio@nowhere ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] && 
        echo "YES, $ISDIR is a directory." ||
        echo "Sorry, $ISDIR is not a directory"
    YES, /home/claudio/Music is a directory.

    [claudio@nowhere ~]$ touch "empty file.txt"
    [claudio@nowhere ~]$ ISDIR="$HOME/empty file.txt" 
    [claudio@nowhere ~]$ [[ $(ls -ld "$ISDIR" | cut -c1) == 'd' ]] && 
        echo "YES, $ISDIR is a directory." || 
        echo "Sorry, $ISDIR is not a directoy"
    Sorry, /home/claudio/empty file.txt is not a directory
file="foo" 
if [[ -e "$file" ]]; then echo "File Exists"; fi;

Если вы хотите проверить, существует ли каталог, независимо от того, настоящий ли это каталог или символическая ссылка, используйте это:

ls $DIR
if [ $? != 0 ]; then
        echo "Directory $DIR already exists!"
        exit 1;
fi
echo "Directory $DIR does not exist..."

Объяснение:Команда «ls» выдает ошибку «ls:/Икс:Нет такого файла или каталога», если каталог или символическая ссылка не существует, а также устанавливает ненулевой код возврата, который можно получить с помощью «$?» (обычно «1»).Обязательно проверьте код возврата сразу после вызова «ls».

(1)

[ -d Piyush_Drv1 ] && echo ""Exists"" || echo "Not Exists"

(2)

[ `find . -type d -name Piyush_Drv1 -print | wc -l` -eq 1 ] && echo Exists || echo "Not Exists"

(3)

[[ -d run_dir  && ! -L run_dir ]] && echo Exists || echo "Not Exists"

Если обнаружена проблема с одним из подходов, описанных выше.

С ls команда;случаи, когда каталог не существует - отображается сообщение об ошибке

$ [[ ls -ld SAMPLE_DIR| grep ^d | wc -l -eq 1]] && echo существует || не существует -ksh:нет:не найден [Нет такого файла или каталога]

Существуют отличные решения, но в конечном итоге каждый скрипт завершится сбоем, если вы находитесь не в правильном каталоге.Итак, кодируйте так:

if [ -d "$LINK_OR_DIR" ]; then 
if [ -L "$LINK_OR_DIR" ]; then
    # It is a symlink!
    # Symbolic link specific commands go here
    rm "$LINK_OR_DIR"
else
    # It's a directory!
    # Directory command goes here
    rmdir "$LINK_OR_DIR"
fi
fi

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

Я понимаю первоначальный вопрос так:для проверки существования каталога независимо от положения пользователя в файловой системе.Поэтому использование команды «найти» может помочь:

dir=" "
echo "Input directory name to search for:"
read dir
find $HOME -name $dir -type d

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

Ниже можно использовать команду find:

find . -type d -name dirname -prune -print
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top