如何检查 Bash shell 脚本中是否存在目录?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/59838/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I check if a directory exists in a Bash shell script?
提问by Grundlefleck
What command can be used to check if a directory exists or not, within a Bash shell script?
在 Bash shell 脚本中,什么命令可用于检查目录是否存在?
回答by Grundlefleck
To check if a directory exists in a shell script, you can use the following:
要检查 shell 脚本中是否存在目录,您可以使用以下命令:
if [ -d "$DIRECTORY" ]; then
# Control will enter here if $DIRECTORY exists.
fi
Or to check if a directory doesn't exist:
或者检查目录是否不存在:
if [ ! -d "$DIRECTORY" ]; then
# Control will enter here if $DIRECTORY doesn't exist.
fi
However, as Jon Ericsonpoints out, subsequent commands may not work as intended if you do not take into account that a symbolic link to a directory will also pass this check. E.g. running this:
但是,正如Jon Ericson指出的那样,如果您不考虑到目录的符号链接也会通过此检查,则后续命令可能无法按预期工作。例如运行这个:
ln -s "$ACTUAL_DIR" "$SYMLINK"
if [ -d "$SYMLINK" ]; then
rmdir "$SYMLINK"
fi
Will produce the error message:
会产生错误信息:
rmdir: failed to remove `symlink': Not a directory
So symbolic links may have to be treated differently, if subsequent commands expect directories:
因此,如果后续命令需要目录,则可能必须对符号链接进行不同的处理:
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
Take particular note of the double-quotes used to wrap the variables. The reason for this is explained by 8jean in another answer.
请特别注意用于包装变量的双引号。8jean在另一个答案中解释了这个原因。
If the variables contain spaces or other unusual characters it will probably cause the script to fail.
如果变量包含空格或其他异常字符,则可能会导致脚本失败。
回答by 8jean
Remember to always wrap variables in double quotes when referencing them in a Bash script. Kids these days grow up with the idea that they can have spaces and lots of other funny characters in their directory names. (Spaces! Back in my days, we didn't have no fancy spaces! ;))
请记住,在 Bash 脚本中引用变量时,始终将它们用双引号括起来。这些天的孩子们在他们的目录名称中可以有空格和许多其他有趣的字符的想法长大。(空格!在我的时代,我们没有花哨的空格!;))
One day, one of those kids will run your script with $DIRECTORY
set to "My M0viez"
and your script will blow up. You don't want that. So use this.
有一天,其中一个孩子会使用$DIRECTORY
set to运行您的脚本,"My M0viez"
而您的脚本会爆炸。你不想那样。所以用这个。
if [ -d "$DIRECTORY" ]; then
# Will enter here if $DIRECTORY exists, even if it contains spaces
fi
回答by Jon Ericson
Note the -dtest can produce some surprising results:
请注意-d测试会产生一些令人惊讶的结果:
$ ln -s tmp/ t
$ if [ -d t ]; then rmdir t; fi
rmdir: directory "t": Path component not a directory
File under: "When is a directory not a directory?" The answer: "When it's a symlink to a directory." A slightly more thorough test:
文件在:“什么时候目录不是目录?” 答案是:“当它是一个目录的符号链接时。” 稍微更彻底的测试:
if [ -d t ]; then
if [ -L t ]; then
rm t
else
rmdir t
fi
fi
You can find more information in the Bash manual on Bash conditional expressionsand the [
builtin commandand the [[
compound commmand.
您可以在 Bash 手册中找到有关Bash 条件表达式和[
内置命令以及[[
复合命令的更多信息。
回答by yukondude
I find the double-bracketversion of test
makes writing logic tests more natural:
我发现双括号版本test
使编写逻辑测试更自然:
if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
echo "It's a bona-fide directory"
fi
回答by elmarco
Shorter form:
更短的形式:
[ -d "$DIR" ] && echo "Yes"
回答by Jorge Barroso
To check if a directory exists you can use a simple if
structure like this:
要检查目录是否存在,您可以使用这样的简单if
结构:
if [ -d directory/path to a directory ] ; then
# Things to do
else #if needed #also: elif [new condition]
# Things to do
fi
You can also do it in the negative:
你也可以否定它:
if [ ! -d directory/path to a directory ] ; then
# Things to do when not an existing directory
Note: Be careful. Leave empty spaces on either side of both opening and closing braces.
注意:小心。在左大括号和右大括号的两侧留空。
With the same syntax you can use:
使用相同的语法,您可以使用:
-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
回答by yoctotutor.com
A simple script to test if a directory or file is present or not:
if [ -d /home/ram/dir ] # For file "if [-f /home/rama/file]" then echo "dir present" else echo "dir not present" fi
A simple script to check whether the directory is present or not:
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
The above scripts will check if the directory is present or not
$?
if the last command is a success it returns "0", else a non-zero value. Supposetempdir
is already present. Thenmkdir tempdir
will give an error like below:mkdir: cannot create directory ‘tempdir': File exists
一个用于测试目录或文件是否存在的简单脚本:
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”,否则返回非零值。假设tempdir
已经存在。然后mkdir tempdir
会报错如下:mkdir: 无法创建目录 'tempdir': 文件存在
回答by kenorb
You can use test -d
(see man test
).
您可以使用test -d
(参见man test
)。
-d file
True if file exists and is a directory.
-d file
如果文件存在并且是目录,则为真。
For example:
例如:
test -d "/etc" && echo Exists || echo Does not exist
Note: The test
command is same as conditional expression [
(see: man [
), so it's portable across shell scripts.
注意:该test
命令与条件表达式[
(参见:)相同man [
,因此它可以跨 shell 脚本移植。
[
- This is a synonym for thetest
builtin, but the last argument must, be a literal]
, to match the opening[
.
[
- 这是test
builtin的同义词,但最后一个参数必须是文字]
,以匹配开头[
.
For possible options or further help, check:
有关可能的选项或进一步的帮助,请检查:
help [
help test
man test
orman [
help [
help test
man test
或者man [
回答by kenorb
Or for something completely useless:
或者对于完全无用的东西:
[ -d . ] || echo "No"
回答by Henk Langeveld
Here's a very pragmatic idiom:
这是一个非常实用的成语:
(cd $dir) || return # Is this a directory,
# and do we have access?
I typically wrap it in a function:
我通常将它包装在一个函数中:
can_use_as_dir() {
(cd ${1:?pathname expected}) || return
}
Or:
或者:
assert_dir_access() {
(cd ${1:?pathname expected}) || exit
}
The nice thing about this approach is that I do not have to think of a good error message.
这种方法的好处是我不必考虑好的错误消息。
cd
will give me a standard one line message to standard erroralready. It will also give more information than I will be able to provide. By performing the cd
inside a subshell ( ... )
, the command does not affect the current directory of the caller. If the directory exists, this subshell and the function are just a no-op.
cd
会给我一个标准的单行消息到标准错误。它还将提供比我能够提供的更多信息。通过cd
在 subshell 内部执行( ... )
,该命令不会影响调用者的当前目录。如果目录存在,这个子shell和函数只是一个空操作。
Next is the argument that we pass to cd
: ${1:?pathname expected}
. This is a more elaborate form of parameter substitution which is explained in more detail below.
接下来是我们传递给cd
:的参数${1:?pathname expected}
。这是一种更复杂的参数替换形式,将在下面更详细地解释。
Tl;dr: If the string passed into this function is empty, we again exit from the subshell ( ... )
and return from the function with the given error message.
Tl; dr:如果传入这个函数的字符串是空的,我们再次退出子shell( ... )
并从函数返回给定的错误信息。
Quoting from the ksh93
man page:
从ksh93
手册页引用:
${parameter:?word}
If
parameter
is set and is non-null then substitute its value; otherwise, printword
and exit from the shell (if not interactive). Ifword
is omitted then a standard message is printed.
如果
parameter
已设置且为非空,则替换其值;否则,打印word
并退出 shell(如果不是交互式的)。如果word
省略,则打印标准消息。
and
和
If the colon
:
is omitted from the above expressions, then the shell only checks whether parameter is set or not.
如果
:
上述表达式中省略了冒号,则 shell 仅检查是否设置了参数。
The phrasing here is peculiar to the shell documentation, as word
may refer to any reasonable string, including whitespace.
这里的措辞是 shell 文档所特有的,word
可以指任何合理的字符串,包括空格。
In this particular case, I know that the standard error message 1: parameter not set
is not sufficient, so I zoom in on the type of value that we expect here - the pathname
of a directory.
在这种特殊情况下,我知道标准错误消息1: parameter not set
是不够的,所以我放大了我们在这里期望的值类型 -pathname
目录的类型。
A philosophical note:
哲学笔记:
The shell is not an object oriented language, so the message says pathname
, not directory
. At this level, I'd rather keep it simple - the arguments to a function are just strings.
shell 不是面向对象的语言,所以消息说pathname
, not directory
。在这个层面上,我宁愿保持简单——函数的参数只是字符串。