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

avatar
Grundlefleck
12 сентября 2008 в 20:06
2930420
35
4009

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

Источник

Ответы (35)

avatar
Grundlefleck
12 сентября 2008 в 20:07
5456

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

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 объясняет в другом ответе.

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

Marc Mutz - mmutz
21 июля 2009 в 16:36
30

Если вы хотите перестраховаться с инструментами GNU, настоятельно рекомендуется использовать -- (маркер конца опций). В противном случае, если ваша переменная содержит что-то похожее на параметр, сценарий завершится ошибкой, как и с пробелами.

fpmurphy
24 марта 2011 в 14:22
2

Для современных версий bash, ksh и т. Д. [...] является встроенным

Keith Thompson
9 августа 2011 в 23:46
83

Следует иметь в виду одну вещь: [ ! -d "$DIRECTORY" ] будет истинным либо если $DIRECTORY не существует, либо если существует, но не является каталогом. Рассмотрим что-то вроде if [ ! -d "$DIRECTORY" ] ; then mkdir "$DIRECTORY" ; fi; это не удастся, если "$DIRECTORY" является файлом. (Конечно, вы все равно должны проверить, удалось ли выполнить mkdir; есть ряд причин, по которым он может потерпеть неудачу.)

Rob Kielty
26 сентября 2012 в 12:52
0

Незначительное примечание. В bash, help [, man test (как уже отмечалось) и info test («Не для UNIX») предоставляют документацию.

Jürgen Paul
26 июля 2013 в 03:45
2

я должен использовать [ ] или [[ ]]?

Alfe
9 сентября 2013 в 11:51
5

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

BlueCacti
15 ноября 2013 в 16:02
0

По какой-то причине я получаю сообщение об ошибке: if [ -d "$TARGET_DIR/$DATE1" ]; then $RSYNC_PARAMS="$RSYNC_PARAMS --link-dest=$TARGET_DIR/$DATE1" fi

BlueCacti
15 ноября 2013 в 16:09
0

DATE1='date -I -d "1 day ago"'; TARGET_DIR="/backup", который является ссылкой; RSYNC_PARAMS="-azrtplH"

ghoti
17 января 2017 в 09:21
12

Вместо тестирования каталога (-d) и символической ссылки (-L) проще просто добавить косую черту к переменной, например if [ -d "${THING:+$THING/}" ]. Каталог не будет возражать против лишней косой черты. Оценка файла будет ложной. Empty останется пустым, поэтому false. И символическая ссылка будет разрешена по назначению. Конечно, это зависит от вашей цели. Если вы хотите перейти туда , это нормально. Если вы хотите удалить его , то код в этом ответе лучше.

henon
3 октября 2017 в 09:41
0

Использование test НЕ работает с отключенным USB-накопителем, поскольку журналирующая FS делает вид, что каталог все еще существует, если вы уже проверяли его ранее. Я обнаружил, что в этом случае проверка кода выхода ls была единственным способом надежно проверить, существует ли каталог: if ls "$DIRECTORY"; then echo "dir exists" ; fi

Danijel
10 января 2019 в 10:40
0

Почему это не работает для относительных путей? Например, ../../../../../my_dir.

Shayan
5 апреля 2020 в 17:41
0

Есть ли разница между -L и -h? На этом веб-сайте gnu.org/savannah-checkouts/gnu/bash/manual/… говорится, что они оба True if file exists and is a symbolic link. Так в чем разница?

William Turrell
5 апреля 2020 в 21:11
0

Пробелы в пределах [ и ], вокруг -d или ! -d важны, иначе сценарий завершится ошибкой, и команда не найдена.

avatar
kenorb
7 мая 2020 в 12:19
9

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

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

mkdir -p /some/directory/you/want/to/exist || exit 1
avatar
Vishal
9 октября 2019 в 06:08
30
DIRECTORY=/tmp

if [ -d "$DIRECTORY" ]; then
    echo "Exists"
fi

Попробуйте в Интернете

Raj
20 февраля 2020 в 06:00
0

запомнить space после [ -> [`` -d . у меня ошибка из-за отсутствия места

Dan Dascalescu
5 марта 2020 в 13:16
4

СНОВА, этот ответ уже был дан в 2008 году с более полезными объяснениями. Единственная новинка здесь - онлайн-площадка.

avatar
Bayou
26 июля 2019 в 15:45
2

В качестве альтернативы параметрам «[-d]» и «[-h]» вы можете использовать stat для получения типа файла и его анализа.

#! /bin/bash
MY_DIR=$1
NODE_TYPE=$(stat -c '%F' ${MY_DIR} 2>/dev/null)
case "${NODE_TYPE}" in
        "directory") echo $MY_DIR;;
    "symbolic link") echo $(readlink $MY_DIR);;
                 "") echo "$MY_DIR does not exist";;
                  *) echo "$NODE_TYPE is unsupported";;
esac
exit 0

Тестовые данные:

$ mkdir tmp
$ ln -s tmp derp
$ touch a.txt
$ ./dir.sh tmp
tmp
$ ./dir.sh derp
tmp
$ ./dir.sh a.txt
regular file is unsupported
$ ./dir.sh god
god does not exist
avatar
Sudip Bhandari
25 июня 2018 в 06:59
5

Используйте программу file. Учитывая, что все каталоги в Linux также являются файлами, достаточно выполнить следующую команду:

file $directory_name

Проверка несуществующего файла: file blah

Вывод: cannot open 'blah' (No such file or directory)

Проверка существующего каталога: file bluh

Вывод: bluh: directory

danger89
7 июня 2019 в 01:03
1

Хорошая идея, но слишком плохая в обоих случаях, команда file всегда возвращает 0 код выхода. Также, когда файл / каталог не может быть найден :(.

avatar
yoctotutor.com
15 мая 2018 в 05:36
139
  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 выдаст ошибку, как показано ниже:

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

Shihe Zhang
6 марта 2019 в 06:47
7

Второй создаст каталог, если сначала его не было. Тогда это не идемпотент.

Chris
7 февраля 2020 в 21:38
2

👆👆👆. Второй кажется опасным. Поскольку он создает каталог, это даже не правда, что каталог отсутствует.

venimus
23 марта 2021 в 23:19
0

mkdir также не создаст полный путь (без параметра), но обратное будет еще более опасным, так как вы даже не можете отменить (rm -f) изменения, поскольку вы не знаете, какие каталоги он создал

avatar
ArtOfWarfare
7 декабря 2017 в 16:24
21

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

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

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.

melMass
7 декабря 2017 в 17:10
2

pushd - для меня самый элегантный способ сделать это. Я собирался опубликовать это как ответ :)

avatar
twitchdotcom slash KANJICODER
13 сентября 2017 в 19:49
3

Git Bash + Dropbox + Windows:

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

#!/bin/bash

dbox="~/Dropbox/"
result=0
prv=$(pwd) && eval "cd $dbox" && result=1 && cd "$prv"
echo $result

read -p "Press Enter To Continue:"

Вы, вероятно, захотите узнать, как успешно перейти к Dropbox из Bash. Итак, вот сценарий целиком.

https://pastebin.com/QF2Exmpn

Gert van den Berg
18 апреля 2018 в 13:07
0

cd - может сильно упростить это ... Или cd "$OLDPWD" (Или используйте подоболочку, в которой каталог вашего скрипта не изменяется, но тогда вы не можете устанавливать переменные)

avatar
Gene
29 июня 2017 в 22:14
3

Из файла сценария myScript.sh :

if [ -d /home/ec2-user/apache-tomcat-8.5.5/webapps/Gene\ Directory ]; then
   echo "Directory exists!"
   echo "Great"
fi

или

if [ -d '/home/ec2-user/apache-tomcat-8.5.5/webapps/Gene Directory' ]; then
   echo "Directory exists!"
   echo "Great"
fi
avatar
Abhishek Gurjar
15 апреля 2017 в 13:36
8

В виде тройной формы,

[ -d "$directory" ] && echo "exist" || echo "not exist"

И с test:

test -d "$directory" && echo "exist" || echo "not exist"
avatar
Brad Parks
15 апреля 2016 в 18:13
12

Этот ответ заключен в сценарий оболочки

Примеры

$ 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";
avatar
David Okwii
23 марта 2016 в 07:25
16

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

[ -d "$DIRECTORY" ] || mkdir $DIRECTORY
Logan Pickup
24 июля 2016 в 21:12
17

Вы можете использовать mkdir -p "$DIRECTORY" для того же эффекта.

codeforester
22 февраля 2021 в 03:55
0

Также нужны двойные кавычки вокруг $DIRECTORY в части mkdir. В противном случае разбиение слов может привести к нежелательным результатам. Например: dir="a b"; mkdir $dir приведет к созданию двух каталогов a и b, а не одного каталога a b.

avatar
Raamesh Keerthi
29 декабря 2015 в 09:45
16

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

if [ -d "$DIRECTORY1" ] && [ -d "$DIRECTORY2" ] then
    # Things to do
fi
perrohunter
3 апреля 2017 в 07:04
0

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

avatar
kenorb
12 сентября 2015 в 21:25
104

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

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

Например:

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

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

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

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

  • help [
  • help test
  • man test или man [
avatar
Piyush Baijal
13 мая 2015 в 07:21
6

(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 exists || not exists

-ksh: not: not found [Нет такого файла или каталога]

Peter Mortensen
7 мая 2020 в 12:18
0

Что означает "выше"? Три командные строки в этом ответе или предыдущих ответах? (Пожалуйста, ответьте, отредактировав свой ответ, а не здесь, в комментариях. Заранее спасибо.).

avatar
Jahid
19 апреля 2015 в 00:54
19
[[ -d "$DIR" && ! -L "$DIR" ]] && echo "It's a directory and not a symbolic link"

Примечание: рекомендуется указывать переменные в кавычках.

Пояснение :

  • -d: проверьте, является ли это каталог
  • -L: проверьте, является ли это символической ссылкой
Peter Mortensen
7 мая 2020 в 12:14
0

Пояснение будет в порядке (отредактировав свой ответ, а не здесь, в комментариях).

avatar
Jorge Barroso
8 апреля 2015 в 02:50
142

Чтобы проверить, существует ли каталог, вы можете использовать простую структуру 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
Dan Dascalescu
5 марта 2020 в 13:14
0

Чем это лучше, чем принятый ответ от 2008 года, если не считать выхода за рамки темы с переключателями файлов?

user1855805
27 марта 2020 в 19:46
0

лучше из-за [! -d каталог / путь к каталогу]

avatar
santosh
5 ноября 2014 в 03:39
26

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

if [ -d "$DIRECTORY" ]; then
    # If true this block of code will execute
fi
Dan Dascalescu
5 марта 2020 в 13:15
0

СНОВА, этот ответ уже давался в 2008 году. Какой смысл его повторять ?!

avatar
Sadhun
13 августа 2014 в 13:41
6

Можно использовать find,

find . -type d -name dirname -prune -print
avatar
derFunk
7 января 2014 в 17:59
4

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

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

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

derFunk
8 января 2014 в 10:51
3

В качестве альтернативы вы можете использовать эту более короткую версию: if ! ls $DIR 2>/dev/null; then echo "$DIR does not exist!"; fi

zerzevul
19 февраля 2021 в 13:25
0

ls возврат ненулевого значения НЕ означает, что каталог существует. Код должен быть: ls $DIR RETURN_CODE=$? if [ "$RETURN_CODE" != "0" ]; then echo "Cannot access directory $DIR (does not exist or no permission or something else altogether)!" exit $RETURN_CODE; fi echo "Directory $DIR already exists..."

avatar
bailey86
25 июля 2013 в 13:12
11

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

if [ -e ${FILE_PATH_AND_NAME} ]
then
    echo "The file or directory exists."
fi
Mark Stewart
29 ноября 2018 в 16:45
1

И не правильно отвечает на вопрос ОП - это каталог?

avatar
Juan Carlos Kuri Pinto
18 апреля 2013 в 22:12
15
[ -d ~/Desktop/TEMPORAL/ ] && echo "DIRECTORY EXISTS" || echo "DIRECTORY DOES NOT EXIST"
Peter Mortensen
7 мая 2020 в 12:07
0

Пояснение будет в порядке (отредактировав свой ответ, а не здесь, в комментариях).

avatar
ajmartin
22 февраля 2013 в 02:39
6
file="foo" 
if [[ -e "$file" ]]; then echo "File Exists"; fi;
Peter Mortensen
7 мая 2020 в 12:07
0

Пояснение будет в порядке (отредактировав свой ответ, а не здесь, в комментариях).

avatar
Henk Langeveld
9 августа 2012 в 21:43
58

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

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

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

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


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

${parameter:?word}

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

и

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

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

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

Философское примечание:

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

F. Hauri
9 февраля 2013 в 20:16
0

Это больше, чем просто проверка на существование: это проверка доступности на вашем уровне пользователя. ТАК вопрос стоит только для существования . Итак, правильный ответ - test -d, как объяснил @Grundlefleck.

Henk Langeveld
9 февраля 2013 в 23:50
8

@ F.Hauri - Он больше ничего не просил, это правда. Однако я обнаружил, что мне обычно нужно знать больше.

Henk Langeveld
2 апреля 2016 в 17:32
0

И мне никогда не приходило в голову, что ни один тест не может быть окончательным, если он не запущен от имени пользователя root. test -d /unreadable/exists завершится ошибкой, даже если аргумент существует.

avatar
dromichaetes
12 декабря 2011 в 20:40
6

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

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

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

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

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

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

sarnold
1 февраля 2012 в 09:29
13

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

avatar
ztank1013
15 сентября 2011 в 19:47
7

Команда 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
ysap
18 февраля 2013 в 17:46
0

+1, но если ISDIR вообще не существует, вы получите сообщение об ошибке, а также диагностическое сообщение.

avatar
muralikrishna
21 апреля 2010 в 06:06
40
if [ -d "$Directory" -a -w "$Directory" ]
then
    #Statements
fi

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

CousinCocaine
28 января 2014 в 08:39
1

-a по сути совпадает с -e. Он объявлен устаревшим, и его использование не рекомендуется.

avatar
user296421
18 марта 2010 в 10:52
9
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
avatar
e-satis
17 февраля 2010 в 17:46
22

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

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), преимущество заключается в больше, чем проблема.

avatar
Silly
17 августа 2009 в 14:02
59

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

[ -d . ] || echo "No"
Jahid
19 апреля 2015 в 00:49
8

Он никогда не напечатает «Нет». Текущий каталог всегда существует, если он не удален другим потоком или другими способами.

Sergey Sargsyan
1 марта 2018 в 21:26
0

Идеальный образец :) учитывая, насколько "уникальны" некоторые ответы по сравнению с принятым ответом

codeforester
4 марта 2018 в 07:35
5

Почему за это так много раз голосовали? Это не отвечает на вопрос.

avatar
8jean
15 сентября 2008 в 22:00
565

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

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

if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists, even if it contains spaces
fi
Jon Ericson
15 сентября 2008 в 22:41
11

Еще одна причина использовать двойные кавычки - это если по какой-то причине $ DIRECTORY не установлен.

michael
12 сентября 2014 в 01:31
2

«всегда заключайте переменные в двойные кавычки ... в сценарии bash». Для bash технически не требуется при использовании [[...]]; см. tldp.org/LDP/abs/html/testconstructs.html#DBLBRACKETS (примечание: без разделения слов): «Между [[и]] не выполняется расширение имени файла или разделение слов, но есть параметр расширение и подстановка команд ".

tvCa
24 декабря 2014 в 13:57
2

В каталогах в Unix / Linux не должно быть пробелов, и впоследствии скрипты не должны быть адаптированы к ним. Достаточно плохо, что Windows поддерживает это со всеми последствиями для сценариев Windows, но, пожалуйста, из любви к чему бы то ни было, не нужно вводить ненужные требования.

JAB
12 августа 2015 в 15:52
21

@tvCa Я считаю, что пользователи обычно предпочитают, чтобы им была предоставлена ​​большая гибкость в именах каталогов, вместо того, чтобы их заставляли упростить работу для разработчиков. (На самом деле, когда я имею дело с длинными именами файлов, я считаю, что файлы без пробелов вызывают боль, поскольку это убивает перенос слов, хотя я сам в прошлом страдал из-за того, что не учитывал пути с пробелами в скриптах и ​​программах.)

Zelphir Kaltstahl
6 мая 2016 в 14:12
0

@JAB Я согласен, но опять же, такие длинные имена каталогов требуют создания нескольких каталогов и лучшей сортировки / категоризации / организации файлов в них.

tripleee
9 июня 2016 в 07:39
1

Это действительно отдельный вопрос; coderhelper.com/questions/10067266/…

uchuugaka
18 октября 2016 в 08:27
2

Ха. Пробелы - это просто символы, у которых обычно нет глифов. В любом случае, вы можете избежать их с помощью обратной косой черты.

Peter - Reinstate Monica
11 октября 2017 в 07:40
1

@tvCa Многие сценарии, которые были счастливы в стандартных средах * nix, внезапно оказываются в средах Windows (вспомните cygwin или git для Windows / Msys2). Или они просто лежат на общих ресурсах Samba. Неслучайно все больше и больше инструментов получают возможность создавать или обрабатывать имена файлов с завершающим NUL.

Gert van den Berg
18 апреля 2018 в 13:22
0

Еще одно преимущество использования переменных в кавычках: производительность - Bash не нужно пытаться разбивать слова на содержимое строки в кавычках. (В основном это ничтожно мало)

tzot
4 сентября 2018 в 15:59
0

IFS="\t\n" очень помогает в сценариях оболочки при работе с пробелами в именах файлов / именах каталогов (где \ t - фактический символ табуляции, а \ n - фактический LF, поэтому он занимает две строки в скрипте :)

jinawee
11 февраля 2019 в 15:00
0

Ваш сценарий взорвется с помощью "~ / my_dir", без ума от детей.

paxdiablo
9 марта 2020 в 23:46
2

Пробелы в именах файлов - зло, я сейчас выполняю миссию с Wowbagger the Infininite Prolonged, чтобы оскорбить всех, кто их использует :-)

avatar
yukondude
12 сентября 2008 в 21:33
230

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

if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
    echo "It's a bona-fide directory"
fi
TheVillageIdiot
19 июня 2011 в 14:48
0

для if [[ -d "$TARFILE" ]] Я получаю [[: не найдено

yukondude
2 июля 2011 в 14:54
15

@TheVillageIdiot и @Hedgehog, вы используете оболочку bash? Двойная скобка поддерживается не везде. Вот ТАК ответ на этот вопрос: coderhelper.com/questions/669452/…

dubiousjim
31 мая 2012 в 15:34
7

А в Busybox ash с параметрами компиляции по умолчанию поддерживается [[ ]], но на самом деле он не предоставляет никаких функций, отличных от [ ]. Если переносимость вызывает беспокойство, придерживайтесь [ ] и используйте необходимые обходные пути.

michael
12 сентября 2014 в 01:23
6

... при использовании конструкций bash в сценарии оболочки первая строка сценария должна быть: #! / bin / bash (а не #! / bin / sh, ksh и т. д.)

Hubert Grzeskowiak
11 августа 2017 в 05:58
2

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

Adam Katz
13 апреля 2020 в 17:05
0

Переносимая версия этого ответа для Posix - if [ -d "$DIRECTORY" ] && ! [ -h "$DIRECTORY ]; then … (-L устарела, -h - его замена. Используйте -L, если вы используете действительно древнюю систему Unix).

Soren Bjornstad
10 января 2021 в 17:59
0

@AdamKatz: -L устарел? В какой системе? Ни help test в Bash, ни справочная или информационная страница GNU coreutils не упоминают об этом.

Adam Katz
11 января 2021 в 00:48
0

@SorenBjornstad - устаревшее - неправильное слово, но на странице руководства для dash говорится: «Этот оператор сохранен для совместимости с предыдущими версиями этой программы. Не полагайтесь на его существование; используйте вместо него -h».

konsolebox
22 мая 2021 в 20:09
0

@AdamKatz Переносимость и отказ от функций в dash не имеют значения, поскольку речь идет о bash.

avatar
elmarco
12 сентября 2008 в 21:08
190

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

# if $DIR is a directory, then print yes
[ -d "$DIR" ] && echo "Yes"
Martijn
5 августа 2016 в 07:38
7

Это работает так: if $dir is a dir, then echo "yes"? Небольшое объяснение поможет :)

tripleee
5 октября 2016 в 04:03
6

cmd && other - это обычное сокращение для if cmd; then other; fi - это работает с большинством языков программирования, поддерживающих логику, и известно как оценка короткого замыкания.

dolmen
23 июля 2018 в 12:40
4

Поведение отличается от set -e (что является передовой практикой программирования оболочки).

tzot
4 сентября 2018 в 16:03
1

@dolmen проверяется [ -d "$DIR" ] (за ним следует && echo Yes), поэтому я считаю, что set -e не влияет на поведение скрипта (т.е. если тест не проходит, скрипт продолжает нормально).

avatar
Jon Ericson
12 сентября 2008 в 20:26
248

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

$ 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 и [ встроенной команде и <984099956329840> составной запятой <984099956329840>.

>
michael
12 сентября 2014 в 01:47
12

или, предполагая, что необходимо работать только с каталогами (и ссылки можно игнорировать) => if [ -d tmpdir -a ! -L tmpdir ]; then echo "is directory"; rmdir tmpdir; fi ... или для одной команды, которая работает как с ссылками, так и с каталогами: rm -r tmpdir

avatar
Neil Neyman
12 сентября 2008 в 20:17
29

Дополнительные функции с использованием 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
    
oHo
18 ноября 2013 в 13:54
0

Привет, Ниль. Ваша идея может быть полезна для проверки существования каталогов в зависимости от шаблона, например: find -maxdepth 1 -type d -name 'pattern'. Вы не возражаете, если я добавлю в ваш ответ этот трюк? Ваше здоровье ;)