Вопрос:

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

shell unix posix

2631269 просмотра

30 ответа

79941 Репутация автора

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

Автор: Grundlefleck Источник Размещён: 12.09.2008 08:06

Ответы (30)


4837 плюса

79941 Репутация автора

Решение

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

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

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

Автор: Grundlefleck Размещён: 12.09.2008 08:07

20 плюса

1758 Репутация автора

Больше возможностей с помощью 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
    
Автор: Neil Neyman Размещён: 12.09.2008 08:17

219 плюса

15717 Репутация автора

Обратите внимание, что тест -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, а также по [встроенной команде и [[составной команде .

Автор: Jon Ericson Размещён: 12.09.2008 08:26

143 плюса

14974 Репутация автора

Короче форма:

[ -d "$DIR" ] && echo "Yes"
Автор: elmarco Размещён: 12.09.2008 09:08

208 плюса

15573 Репутация автора

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

if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
    echo "It's a bona-fide directory"
fi
Автор: yukondude Размещён: 12.09.2008 09:33

505 плюса

7454 Репутация автора

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

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

if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists, even if it contains spaces
fi
Автор: 8jean Размещён: 15.09.2008 10:00

54 плюса

0 Репутация автора

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

[ -d . ] || echo "No"
Автор: Silly Размещён: 17.08.2009 02:02

20 плюса

373456 Репутация автора

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

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), выгода больше, чем проблема.

Автор: e-satis Размещён: 17.02.2010 05:46

7 плюса

0 Репутация автора

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
Автор: user296421 Размещён: 18.03.2010 10:52

36 плюса

369 Репутация автора

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

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

Автор: muralikrishna Размещён: 21.04.2010 06:06

6 плюса

4653 Репутация автора

Команда 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
Автор: ztank1013 Размещён: 15.09.2011 07:47

4 плюса

73 Репутация автора

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

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' ничего не выведет на стандартный вывод (на мой вкус, это не изящное решение) и, тем не менее, будет иметь нулевой выход. Может быть, кто-то может улучшить это.

Автор: dromichaetes Размещён: 12.12.2011 08:40

47 плюса

5949 Репутация автора

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

(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опущено, то печатается стандартное сообщение.

а также

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

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

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

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

Автор: Henk Langeveld Размещён: 09.08.2012 09:43

5 плюса

1330 Репутация автора

file="foo" 
if [[ -e "$file" ]]; then echo "File Exists"; fi;
Автор: ajmartin Размещён: 22.02.2013 02:39

12 плюса

889 Репутация автора

[ -d ~/Desktop/TEMPORAL/ ] && echo "DIRECTORY EXISTS" || echo "DIRECTORY DOES NOT EXIST"
Автор: Juan Carlos Kuri Pinto Размещён: 18.04.2013 10:12

10 плюса

216 Репутация автора

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

if [ -e ${FILE_PATH_AND_NAME} ]
then
    echo "The file or directory exists."
fi
Автор: bailey86 Размещён: 25.07.2013 01:12

5 плюса

1035 Репутация автора

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

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

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

Автор: derFunk Размещён: 07.01.2014 05:59

96 плюса

1108 Репутация автора

if [ -d "$DIRECTORY" ]; then  
    # Here if $DIRECTORY exists  
fi
Автор: Ayyappa Boligala Размещён: 15.04.2014 08:07

4 плюса

152 Репутация автора

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

find . -type d -name dirname -prune -print
Автор: Sadhun Размещён: 13.08.2014 01:41

25 плюса

295 Репутация автора

Введите этот код в Bash Promt

if [ -d "$DIRECTORY" ]; then
  # if true this block of code will execute
fi
Автор: santosh Размещён: 05.11.2014 03:39

124 плюса

1396 Репутация автора

Чтобы проверить, существует ли каталог, вы можете использовать простую структуру 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 
Автор: Jorge Barroso Размещён: 08.04.2015 02:50

14 плюса

14467 Репутация автора

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

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

Автор: Jahid Размещён: 19.04.2015 12:54

5 плюса

171 Репутация автора

(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: not: not found [Нет такого файла или каталога]

Автор: Piyush Baijal Размещён: 13.05.2015 07:21

8 плюса

78936 Репутация автора

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

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

mkdir -p /some/directory/you/want/to/exist || exit 1
Автор: kenorb Размещён: 12.09.2015 09:21

84 плюса

78936 Репутация автора

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

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

Например:

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

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

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

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

  • help [
  • help test
  • man test или же man [
Автор: kenorb Размещён: 12.09.2015 09:25

16 плюса

328 Репутация автора

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

if [ -d "$DIRECTORY1" ] && [ -d "$DIRECTORY2" ] then
    # Things to do
fi
Автор: Raamesh Keerthi Размещён: 29.12.2015 09:45

15 плюса

5126 Репутация автора

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

[ -d "$DIRECTORY" ] || mkdir $DIRECTORY
Автор: David Okwii Размещён: 23.03.2016 07:25

11 плюса

32414 Репутация автора

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

Примеры

$ 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";
Автор: Brad Parks Размещён: 15.04.2016 06:13

17 плюса

13310 Репутация автора

Рассматривали ли вы просто делать то, что вы хотите сделать, 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выполнить ваш блок.

Автор: ArtOfWarfare Размещён: 07.12.2017 04:24

89 плюса

2626 Репутация автора

  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
    

    Вышеуказанные скрипты будут проверять, присутствует ли каталог или нет

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

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

Автор: yoctotutor.com Размещён: 15.05.2018 05:36
32x32