问答中心分类: BASH如何检查 Bash shell 脚本中是否存在目录?
0
kenorb 提问 1月 前

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

29 Answers
0
8jean 回答 1月 前

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

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

这些天来,孩子们在他们的目录名称中添加了空格和许多其他有趣的字符。 (空间!在我那个年代,我们没有花哨的空间!)有一天,其中一个孩子会运行你的脚本$DIRECTORY调成"My M0viez"你的脚本会爆炸。你不想要那个。所以使用双引号。

Jon Ericson 回复 1月 前

使用双引号的另一个原因是 $DIRECTORY 由于某种原因未设置。

michael 回复 1月 前

“总是将变量用双引号括起来……在 bash 脚本中。”对于 bash,使用 [[…]] 时在技术上不是必需的;看tldp.org/LDP/abs/html/testconstructs.html#DBLBRACKETS(注意:没有分词):“[[和]]之间没有文件名扩展或分词,但有参数扩展和命令替换。”

tvCa 回复 1月 前

Unix/Linux 上的目录不应该有任何空格,随后的脚本也不应该适应它。 Windows 支持它已经够糟糕了,这对 Windows 脚本产生了所有后果,但是出于对任何事物的热爱,请不要引入不必要的要求。

JAB 回复 1月 前

@tvCa 我发现用户通常更喜欢允许他们的目录名称具有更大的灵活性,而不是被迫让开发人员的事情变得更容易。 (事实上​​,在处理长文件名时,我发现没有空格的文件名很痛苦,因为这会扼杀自动换行,尽管我自己过去曾因不考虑脚本和程序中带有空格的路径而受苦。)

Zelphir Kaltstahl 回复 1月 前

@JAB我同意,但是如此长的目录名称再次要求制作多个目录并更好地将文件分类/分类/组织到这些目录中。

tripleee 回复 1月 前

这确实是一个单独的问题;stackoverflow.com/questions/10067266/…

uchuugaka 回复 1月 前

哈。空格只是通常没有字形的字符。无论如何,你可以用反斜杠转义它们。

Peter - Reinstate Monica 回复 1月 前

@tvCa 许多在标准 *nix 环境中很满意的脚本突然发现自己在 Windows 环境中(想想 cygwin,或 Windows/Msys2 的 git)。或者他们只是在 Samba 股票上松了一口气。越来越多的工具可以选择生成或处理 NUL 终止的文件名,这并非巧合。

Gert van den Berg 回复 1月 前

引用变量的另一个优点:性能 – Bash 不需要尝试对引用字符串的内容进行分词。 (大部分可以忽略不计)

tzot 回复 1月 前

IFS="\t\n"在处理文件名/目录名中的空格时,对 shell 脚本有很大帮助(其中 \t 是一个实际的制表符,\n 是一个实际的 LF,所以这在脚本中占据了两行 🙂

jinawee 回复 1月 前

你的脚本会被“~/my_dir”炸毁,不需要疯狂的孩子。

paxdiablo 回复 1月 前

文件名中的空格是邪恶的,我目前正在执行一项任务,与无限延长的 Wowbagger 一起侮辱所有使用它们的人:-)

mattst 回复 1月 前

文件名中的空格,很好,感叹号和&符号,没问题,但是为什么哦,为什么有人会觉得需要在文件名中添加换行符?!

David Ongaro 回复 1月 前

Unix 允许除 NUL 和/从一开始就在文件或目录名中。那是 VFAT 出现之前的几十年。

0
Jon Ericson 回答 1月 前

注意-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 条件表达式[内置命令[[复合命令.

michael 回复 1月 前

或者,假设只需要处理目录(并且可以忽略链接)=>if [ -d tmpdir -a ! -L tmpdir ]; then echo "is directory"; rmdir tmpdir; fi…或者,对于一个同时适用于链接和目录的命令:rm -r tmpdir

0
yukondude 回答 1月 前

我发现双括号版本test使编写逻辑测试更自然:

if [[ -d "${DIRECTORY}" && ! -L "${DIRECTORY}" ]] ; then
    echo "It's a bona-fide directory"
fi
TheVillageIdiot 回复 1月 前

为了if [[ -d "$TARFILE" ]]我得到 [[: 未找到

yukondude 回复 1月 前

@TheVillageIdiot 和@Hedgehog,您使用的是 bash shell 吗?双括号不是普遍支持的。这是一个关于这一点的答案:stackoverflow.com/questions/669452/…

dubiousjim 回复 1月 前

在带有默认编译选项的 Busybox ash 中[[ ]]受支持,但实际上并未提供任何不同的功能[ ].如果便携性是一个问题,坚持[ ]并使用必要的解决方法。

michael 回复 1月 前

…如果在 shell 脚本中使用 bash 结构,则脚本的第一行应该是:#!/bin/bash(而不是 #!/bin/sh、ksh 等)

Hubert Grzeskowiak 回复 1月 前

在 bash 中使用方括号时,不需要引用变量。

Adam Katz 回复 1月 前

这个答案的可移植 Posix 版本是if [ -d "$DIRECTORY" ] && ! [ -h "$DIRECTORY ]; then …(-L已弃用,-h是它的替代品。利用-L如果你使用的是一个非常古老的 Unix 系统)。

Soren Bjornstad 回复 1月 前

@亚当卡茨:-L已弃用?在什么系统中?两者都不help test在 Bash 中,GNU coreutils 手册页或信息页都提到了这一点。

Adam Katz 回复 1月 前

@SorenBjornstad – deprecated 不是正确的词,而是手册页dash说“保留此运算符是为了与该程序的先前版本兼容。不要依赖它的存在;使用-h反而。”

konsolebox 回复 1月 前

@AdamKatz 可移植性和破折号功能的弃用无关紧要,因为这是关于 bash 的。

0
elmarco 回答 1月 前

较短的形式:

# if $DIR is a directory, then print yes
[ -d "$DIR" ] && echo "Yes"
Martijn 回复 1月 前

这是否像这样工作:if $dir is a dir, then echo "yes"?一点解释会有所帮助:)

tripleee 回复 1月 前

cmd && other是常用的简写形式if cmd; then other; fi— 这适用于大多数支持布尔逻辑的编程语言,被称为短路评估.

dolmen 回复 1月 前

下的行为不一样set -e(这是一个shell 编程最佳实践)。

tzot 回复 1月 前

@dolmen[ -d "$DIR" ]检查(后跟&& echo Yes),所以我相信set -e对脚本行为没有影响(即如果测试失败,脚本会正常继续)。

dan 回复 1月 前

@dolmen 这是不正确的。下的行为完全相同set -e.除了如果回声失败,脚本将退出。[ -d "$DIR" ]一个人(没有&& cmd ...) 将导致脚本退出set -e,如果测试失败(即目录不存在,或者$DIR存在但不是目录)。

0
yoctotutor.com 回答 1月 前
  1. 一个简单的脚本来测试目录或文件是否存在:
    if [ -d /home/ram/dir ]   # For file "if [ -f /home/rama/file ]"
     then
         echo "dir present"
     else
         echo "dir not present"
     fi
  2. 一个简单的脚本来检查目录是否存在:
    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’: 文件存在

Shihe Zhang 回复 1月 前

第二个将创建目录,如果它一开始不存在的话。那么它不是幂等的。

Chris 回复 1月 前

👆👆👆。第二个好像很危险。由于它创建了目录,因此该目录不存在甚至不再是真的。

venimus 回复 1月 前

mkdir 也不会创建完整路径(没有参数),但相反会更危险,因为您甚至无法还原(rm -f)更改,因为您不知道它创建了哪些目录