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

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

30 ответов


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

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 в другом ответе.

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


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

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

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

Примечание - d тест может дать некоторые удивительные результаты:

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

файл в разделе: "когда каталог не является каталогом? Ответ: "когда это символическая ссылка на каталог.- Чуть более тщательный тест:--7-->

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

вы можете найти более подробную информацию в руководстве Bash на Баш условные выражения и [ встроенная команда и [[ соединение commmand.


найти двойной кронштейн версия 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 true, если файл существует и является каталогом.

например:

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

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

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

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

  • help [
  • help test
  • man test или man [

или для чего-то совершенно бесполезного:

[ -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 внутри подуровень ( ... ) команда не влияет текущий каталог вызывающего абонента. Если каталог существует, эта подрешетка и функция являются просто no-op.

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

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


слово ksh93 man page:

${parameter:?word}

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

и

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

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

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

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


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

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


  1. простой скрипт для проверки наличия или отсутствия dir или файла:

    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
    

    вышеупомянутые скрипты будут проверять, присутствует ли dir или нет

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

    команды mkdir: невозможно создать каталог ' tempdir’: файл существует


введите этот код на bash promt

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


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

N. B: цитирование переменных-хорошая практика.


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

[ -d "$DIRECTORY" ] || mkdir $DIRECTORY

[ -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 [ "" == "help" ]
then
  show_help
fi
if [ -z "" ]
then
  show_help
fi

DIR=
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

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

Therfore:

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

на в сочетании с -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: /x: нет такого файла или каталога", если каталог или символическая ссылка не существует, а также устанавливает код возврата, который вы можете получить через"$?"для не-null (обычно "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

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


ниже найти можно использовать,

find . -type d -name dirname -prune -print