在一个shell脚本中,可以用什么命令来检查一个目录是否存在?
要检查一个目录在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
然而,正如Jon Ericson所指出的,如果你没有考虑到一个目录的符号链接也会通过这个检查,那么后续的命令可能不会按预期工作。 例如,运行这个。
ln -s "$ACTUAL_DIR" "$SYMLINK"
if [ -d "$SYMLINK" ]; then
rmdir "$SYMLINK"
fi
将产生错误信息。
因此,如果后续的命令希望得到目录,那么符号链接可能要被区别对待。
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
文件名:"目录何时不是目录?" 答案是:"当它是一个目录的符号链接时。" 一个稍微彻底的测试。
if [ -d t ]; then
if [ -L t ]; then
rm t
else
rmdir t
fi
fi
你可以在Bash手册中找到更多关于Bash条件表达式和[[
内置命令](https://www.gnu.org/software/bash/manual/bash.html#index-_005b)以及[`[`复合命令](https://www.gnu.org/software/bash/manual/bash.html#index-_005b_005b)的信息。
要检查一个目录是否存在,你可以使用简单的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
if [-d /home/ram/dir] # for file "if [-f /home/rama/file]" 那么 echo "dir present" 否则 echo "dir not present" fi
mkdir tempdir # 如果你想检查文件,就用touch代替mkdir ret=$? 如果[ "$ret" == "0" ] 然后 echo "dir present" 否则 echo "dir not present" fi
上述脚本将检查dir是否存在。
$?
如果最后一个命令成功,则返回"0"。
否则返回非零值。
假设 "tempdir "已经存在,那么 "mkdir tempdir "会给出如下错误信息。
>.mkdir: mkdir: tempdir mkdir: 不能创建目录'tempdir'。 文件存在
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 -d "/etc" && echo Exists || echo Does not exist
注:"test "命令与条件表达式"[`"相同。
test命令与条件表达式
[相同(见:
man [`),所以它可以跨shell脚本移植。
gt;
[- 这是内置
test的同义词,但最后一个参数必须是字面的
],以匹配开头的
[`。
关于可能的选项或进一步的帮助,请检查。
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中。
它还会给出比我能够提供的更多信息。
通过在一个子壳( .... )
,该命令不影响调用者的当前目录。
如果目录存在,这个子shell和函数就只是一个无操作。
接下来是我们传递给cd
的参数。
${1:?pathname expected}
。
这是一种比较复杂的参数替换形式,下面会详细解释。
Tl;dr:
如果传入这个函数的字符串是空的,我们再次从子壳( ... ... )
中退出,并从函数中返回。
)`,并带着给定的错误信息从函数中返回。
引自ksh93
man页面。
${parameter:?word}
>.如果 "参数 "被设置且为非空,则用其值代替;
如果 "参数 "被设置且为非空,则用其值代替。
>.否则,打印word
并退出shell(如果不是交互式)。
否则,打印word
并退出shell(如果不是交互式)。
如果
参数
被设置且非空,则用它的值代替; > 否则,打印word
并从shell中退出(如果不是交互式)。 如果省略了word
,则打印一个标准信息。
和
如果上述表达式中省略了冒号":`",那么就会出现
shell只检查参数是否被设置。
这里的措辞是shell文档中特有的,因为word
可能指的是
到任何合理的字符串,包括空格。
在这种特殊情况下,我知道标准错误信息 "1. 参数未设置 "是不够的,所以我放大了我们在这里期望的值类型--目录的 "路径名"。 参数未设置 "是不充分的,所以我放大了我们所期望的值的类型--目录的 "路径名"。
一个哲学上的说明。
shell不是一种面向对象的语言,所以消息说的是pathname
,而不是directory
。
在这个层面上,我宁愿保持简单--函数的参数只是字符串。
find
的更多功能检查子目录中的文件夹是否存在。
found=`find -type d -name "myDirectory"`。
如果 [ -n "$found"] 则
那么
# 变量'found'包含"myDirectory"所在的完整路径。
# 如果有多个名为"myDirectory"的文件夹,它可能包含多行。
fi
根据当前目录中的模式,检查一个或几个文件夹的存在。
found=`find -maxdepth 1 -type d -name "my*"`。
如果 [ -n "$found"] 则
那么
# 变量 'found'包含找到文件夹"my*"的完整路径。
fi
*两种组合。在下面的例子中,它检查文件夹在当前目录下是否存在。
found=`find -maxdepth 1 -type d -name "myDirectory"`。
如果 [ -n "$found"] 则
那么
# 变量 'found'不是空的 => "myDirectory"`存在。
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 "中做任何你想做的事情,而不是在你跳跃之前先看看?
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
块执行。