Проверьте, существует ли каталог в сценарии оболочки
какая команда может использоваться для проверки, существует ли каталог или нет, в сценарии оболочки?
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
чтобы проверить, существует ли каталог, вы можете использовать простую структуру 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
можно использовать 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 [
вот очень прагматичная идиома:
(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
устанавливается и не является нулевым, а затем заменяет его значение; в противном случае, printword
и выход из оболочки (если не интерактивные). Еслиword
опущено, затем печатается стандартное сообщение.
и
если опущено из приведенных выше выражений, затем shell только проверяет, установлен ли параметр или не.
фразировка здесь свойственна документации оболочки, как word
может относиться
к любой разумной строке, включая пробелы.
в данном конкретном случае, я знаю, что стандартное сообщение об ошибке 1: parameter not set
недостаточно, поэтому я увеличиваю тип значения, которое мы ожидаем здесь -pathname
каталог.
в philosphical Примечание:
Оболочка не является объектно-ориентированным языком, поэтому в сообщении говорится pathname
, а не directory
. На на этом уровне я бы предпочел сохранить его простым - аргументы функции-это просто строки.
if [ -d "$Directory" -a -w "$Directory" ]
then
#Statements
fi
приведенный выше код проверяет, существует ли каталог и доступен ли он для записи.
-
простой скрипт для проверки наличия или отсутствия dir или файла:
if [ -d /home/ram/dir ] # for file "if [-f /home/rama/file]" then echo "dir present" else echo "dir not present" fi
-
простой скрипт для проверки наличия или отсутствия каталога:
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: цитирование переменных-хорошая практика.
ответ завернутый как сценарий оболочки
примеры
$ 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
Если вы хотите проверить, существует ли каталог, независимо от того, является ли это реальным каталогом или символической ссылкой, используйте это:
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 (не элегантное решение на мой вкус) и, тем не менее, будет иметь нулевой выход. Возможно, кто-то мог бы улучшить это.