什么命令检查Bash shell脚本中是否存在目录?


当前回答

在Bash脚本中引用变量时,始终将变量括在双引号中。

if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists, even if it contains spaces
fi

现在的孩子们在他们的目录名中添加空格和许多其他有趣的字符。(空间!在我的时代,我们没有花哨的空间!)有一天,这些孩子中的一个会运行你的脚本,$DIRECTORY设置为“My M0viez”,你的脚本就会崩溃。你不想这样。所以使用双引号。

其他回答

if [ -d "$DIRECTORY" ]; then
    # Will enter here if $DIRECTORY exists
fi

这不是完全正确的。。。

如果要转到该目录,还需要具有该目录的执行权限。也许你也需要写权限。

因此:

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

这里有一个非常实用的成语:

(cd $dir) || return # Is this a directory,
                    # and do we have access?

我通常将其包装在函数中:

can_use_as_dir() {
    (cd ${1:?pathname expected}) || return
}

Or:

assert_dir_access() {
    (cd ${1:?pathname expected}) || exit
}

这种方法的好处是,我不必想到好的错误消息。

cd会给我一条标准的单行消息,告诉我标准错误。它还将提供我无法提供的更多信息。通过在子shell(…)中执行cd,该命令不会影响调用者的当前目录。如果目录存在,则此子shell和函数只是一个no-op。

接下来是传递给cd:${1:?路径名应为}的参数。这是一种更为复杂的参数替换形式,将在下面进行更详细的解释。

T1;dr:如果传入此函数的字符串为空,我们将再次从子shell(…)退出,并返回带有给定错误消息的函数。


引用ksh93手册页:

${parameter:?word}

若参数设置为非空,则替换其值;否则,打印word并退出shell(如果不是交互式的)。若单词被省略,则打印标准消息。

and

如果在上述表达式中省略冒号:,则shell只检查是否设置了参数。

这里的措辞是shell文档特有的,因为单词可以指任何合理的字符串,包括空格。

在这种特殊情况下,我知道标准错误消息1:parameter not set是不够的,所以我放大了我们期望的值类型——目录的路径名。

哲学笔记:

shell不是面向对象的语言,因此消息中显示的是路径名,而不是目录。在这个层次上,我宁愿保持简单——函数的参数只是字符串。

使用-e检查将检查文件,其中包括目录。

if [ -e ${FILE_PATH_AND_NAME} ]
then
    echo "The file or directory exists."
fi

更多功能使用查找

检查子目录中是否存在文件夹:find=`find-type d-name“myDirectory”`如果[-n“$found”]然后#变量“find”包含“myDirectory”所在的完整路径。#如果有多个名为“myDirectory”的文件夹,它可能包含多行。传真根据当前目录中的模式检查是否存在一个或多个文件夹:found=`find-maxdepth 1-type d-name“my*”`如果[-n“$found”]然后#变量“find”包含找到文件夹“my*”的完整路径。传真两种组合。在以下示例中,它检查当前目录中是否存在文件夹:find=`find-maxdeph 1-type d-name“myDirectory”`如果[-n“$found”]然后#变量'found'不为空=>“myDirectory”`存在。传真

注意-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条件表达式、内置命令和[[复合命令的更多信息。