Какую команду можно использовать для проверки наличия или отсутствия каталога в оболочке script?
Чтобы проверить, существует ли каталог в сценарии оболочки, вы можете использовать следующее:
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 a directory!
# Directory command goes here.
rmdir "$LINK_OR_DIR"
fi
fi
Обратите особое внимание на двойные кавычки, используемые для переноса переменных, причина этого объясняется 8jean в другом ответе.
Если переменные содержат пробелы или другие необычные символы, это может привести к сбою сценария.
Не забудьте всегда переносить переменные в двойные кавычки, ссылаясь на них в a bash script. Дети в эти дни растут с идеей, что они могут иметь пробелы и множество других забавных персонажей в своих именах каталогов. (Пространства! В мои дни у нас не было никаких фантастических пространств!))
Однажды один из этих детей запустит ваш script с $DIRECTORY
, установленным на "My M0viez"
, и ваш script взорвется. Вы этого не хотите. Поэтому используйте это.
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
Файл под: "Когда каталог не является каталогом?" Ответ: "Когда это символическая ссылка на каталог". Немного более тщательное испытание:
if [ -d t ]; then
if [ -L t ]; then
rm t
else
rmdir t
fi
fi
Дополнительную информацию в руководстве Bash можно найти в Bash условных выражениях и [
встроенная команда и [[
составная комм..
if [ -d tmpdir -a ! -L tmpdir ]; then echo "is directory"; rmdir tmpdir; fi
... или, для одной команды, которая работает с обоими ссылками и каталогами: rm -r tmpdir
Я нахожу версию с двумя скобками test
делает естественные логические тесты написания:
if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
echo "It a bona-fide directory"
fi
if [[ -d "$TARFILE" ]]
я получаю [[: не найдено
Более короткая форма:
[ -d "$DIR" ] && echo "Yes"
if $dir is a dir, then echo "yes"
? Немного объяснения поможет :)
cmd && other
- это обычное сокращение для if cmd; then other; fi
- это работает с большинством языков программирования, которые поддерживают булеву логику, и называется оценкой короткого замыкания .
Чтобы проверить, существует ли каталог, вы можете использовать простую структуру, например:
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 [
Или для чего-то совершенно бесполезного:
[ -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}
. Это более сложная форма замещения параметров, которая более подробно объясняется ниже.
Tl; dr: Если строка, переданная в эту функцию, пуста, мы снова выходим из подоболочки ( ... )
и возвращаемся от функции с данным сообщением об ошибке.
Цитата из справочной страницы ksh93
:
${parameter:?word}
Если
parameter
установлено и не равно null, замените его значение; в противном случае напечатайтеword
и выйдите из оболочки (если не интерактивно). Еслиword
опущено, выводится стандартное сообщение.
и
Если двоеточие
:
не указано в приведенных выше выражениях, shell проверяет, установлен ли параметр или нет.
Обозначение здесь относится к документации оболочки, поскольку word
может ссылаться
любой разумной строке, включая пробелы.
В этом конкретном случае я знаю, что стандартное сообщение об ошибке 1: parameter not set
недостаточно, поэтому я увеличиваю тип ожидаемого здесь значения - pathname
каталога.
Философская заметка:
Оболочка не является объектно-ориентированным языком, поэтому сообщение говорит pathname
, а не directory
. На этом уровне я бы предпочел сохранить его простым - аргументы функции являются просто строками.
test -d
как объяснил @Grundlefleck.
if [ -d "$Directory" -a -w "$Directory" ]
then
#Statements
fi
Вышеприведенный код проверяет, существует ли каталог и доступен ли он.
Введите этот код в bash promt
if [ -d "$DIRECTORY" ]; then
# if true this block of code will execute
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 a dir";
fi
Не нужно беспокоиться о пробелах и специальных символах, пока вы используете "${}"
.
Обратите внимание, что [[]]
не так переносится, как []
, но поскольку большинство людей работают с современными версиями Bash (поскольку в конце концов большинство людей даже не работают с командной строкой: -p), выгода больше, чем проблема.
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
find -maxdepth 1 -type d -name 'pattern'
. Вы не против, если я добавлю в ваш ответ этот трюк? Ура;)
Простой скрипт для проверки наличия или отсутствия файла или файла:
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
Вышеприведенные скрипты будут проверять, присутствует ли каталог или нет.
$?
если последний успешный процесс возвращает значение "0" else, отличное от нуля. предположим, что tempdir
уже присутствует, тогда mkdir tempdir
даст ошибку, как mkdir tempdir
ниже:
mkdir: невозможно создать каталог tempdir: Файл существует
Чтобы проверить несколько каталогов, используйте этот код:
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
cd
, mv
, rm
, и т.д... если вы попробуете их на файлы, которые не существуют, они будут выходить с ошибкой и распечатать сообщение о том, что не существует, и ваш, then
блок будет пропускаются. Если вы попробуете их в существующих файлах, команда выполнит и завершит со статусом 0
, что позволит выполнить then
блок.
Проверьте, существует ли каталог, иначе сделайте один
[ -d "$DIRECTORY" ] || mkdir $DIRECTORY
mkdir -p "$DIRECTORY"
для того же эффекта.
[[ -d "$DIR" && ! -L "$DIR" ]] && echo "It a directory and not a symbolic link"
N.B: Котировочные переменные являются хорошей практикой.
[ -d ~/Desktop/TEMPORAL/ ] && echo "DIRECTORY EXISTS" || echo "DIRECTORY DOES NOT EXIST"
Этот ответ завершен как оболочка script
$ 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
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
будет проверять файлы, включая каталоги.
if [ -e ${FILE_PATH_AND_NAME} ]
then
echo "The file or directory exists."
fi
По Jonathan комментарий:
Если вы хотите создать каталог, и он еще не существует, то самым простым методом является использование 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
Команда 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
(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]] && & эхо существует || не существует
-ksh: not: not found [Нет такого файла или каталога]
Если вы хотите проверить, существует ли каталог, независимо от того, является ли это реальной директорией или символической ссылкой, используйте это:
ls $DIR
if [ $? != 0 ]; then
echo "Directory $DIR already exists!"
exit 1;
fi
echo "Directory $DIR does not exist..."
Объяснение: Команда "ls" дает ошибку "ls:/x: Нет такого файла или каталога", если каталог или символическая ссылка не существует, а также устанавливает код возврата, который вы можете получить с помощью "$?"., до ненулевой (обычно "1" ). Обязательно проверьте код возврата непосредственно после вызова "ls".
if ! ls $DIR 2>/dev/null; then echo "$DIR does not exist!"; fi
file="foo"
if [[ -e "$file" ]]; then echo "File Exists"; fi;
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. Итак, вот в нем script.
cd -
может сильно упростить это ... Или cd "$OLDPWD"
(или использовать подоболочку, которая не меняется в cd "$OLDPWD"
вашего скрипта, но тогда вы не можете устанавливать переменные)
Ниже можно использовать
find . -type d -name dirname -prune -print
Отличные решения там, но в конечном итоге каждый script завершится неудачно, если вы не находитесь в правильном каталоге. Итак, код выглядит следующим образом:
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 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 (не элегантное решение на мой вкус) и, тем не менее, будет иметь нулевой выход. Может быть, кто-то может улучшить это.
locate
но не подходит ни для чего другого ...
Как насчет file
программы. Учитывая, что все каталоги также являются файлами в linux, достаточно выполнить следующую команду:
file $directory_name
Проверка несуществующего файла: file blah
Выход: cannot open 'blah' (No such file or directory)
Проверка существующего каталога: file bluh
Выход: bluh: directory
Из Script файла 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
В виде тройной формы
[ -d "$directory" ] && echo "exist" || echo "not exist"
И с тестом
test -d "$directory" && echo "exist" || echo "not exist"
--
(маркер конца опций). В противном случае, если ваша переменная содержит нечто, похожее на параметр, скрипт завершится с ошибкой, как и с пробелами.