这个bash脚本中的if语句是做什么的?

7

我是一名新手,正在通过一些示例来学习bash脚本编写。其中一个示例是使用if语句来测试先前分配的输出文件是否有效,如下所示:

if [ -n "$outputFile" ] && ! 2>/dev/null : >> $outputFile ; then
    exit 1
fi

我理解 [ -n "$outputFile" ] 的含义,但不理解条件语句的其他部分。有人可以解释一下 ! 2>/dev/null : >> $outputFile 是什么意思/做什么吗?
我已经谷歌搜索了答案,但大多数链接都是关于I/O重定向的解释,这些解释肯定是相关的,但对于 ! : >> 结构仍然不清楚。

你在哪里看到它的?它说它能做什么? - Mark Setchell
可以重写为 if [[ $outputFile ]] && [[ ! -w $outputFile ]]; then exit; fi - glenn jackman
@glennjackman: -w 假设文件已经存在,所以它并不完全相同。 - FatalError
@MarkSetchell,我在这个脚本中找到了if语句:链接。该脚本的基本思想是将运行进程的I/O重定向到指定文件。if语句用于在dupx中测试文件是否可写。 - BigHead
2个回答

5

这是一些奇怪的代码!

: 命令是内置于 bash 的。它相当于 true;它成功地什么也不做。

: >> $outputFile

尝试不执行任何操作,并将(空)输出追加到$outputFile - 已确认其为非空字符串。如果不存在文件,则重定向运算符>>将创建该文件。

I/O重定向,如2>/dev/null,可以出现在简单命令的任何位置; 它们不必在末尾。因此,: 命令的stdout(为空)被附加到$outputFile,并且任何stderr输出都被重定向到/dev/null。任何这样的stderr输出都是重定向失败的结果,因为 : 命令本身不做任何事情,不会未能做到。我不知道stdout的重定向(到$outputFile的末尾)和stderr的重定向(到/dev/null)为什么在:命令的两侧。

! 运算符是逻辑“非”; 它检查以下命令是否成功,并反转结果。

总的来说,用类英语文本写成:

如果"$outputFile"已设置且不是空字符串,而且如果我们没有写入它的权限,则以状态码1终止脚本。

简而言之,它测试我们是否能够写入$outputFile,如果不能则退出。


1
非常感谢详细的解释!关于为什么“将stderr重定向(到/dev/null)放在:命令的两侧”,我进行了一些测试。我创建了一个只读文件/tmp/bob,并运行了2>/dev/null : >> /tmp/bob: >> /tmp/bob 2>/dev/null。前者不打印任何内容,而后者打印“bash:/tmp/bob:权限被拒绝”。 - BigHead
@GongyuWang:很奇怪;在执行2>/dev/null : >> /tmp/bob之后,我得到的 $? 值为0(并且 /tmp/bob 文件为空)。如果我首先将 /tmp/bob 创建为目录或者一个我无法写入的文件,则 $? 值为1(现在我实际上已经阅读了您的整个评论,意识到这就是您所做的事情)。 - Keith Thompson
1
@GongyuWang:我可以通过使用 : 2>/dev/null >> /tmp/bob 来避免错误消息。2>/dev/null 必须在 >> /tmp/bob 之前;它不必在 : 命令之前。 - Keith Thompson
我对bash中的if语句工作方式感到困惑。我以为它像C语言一样,但实际上不是这样的,“如果条件部分的返回状态为零,则执行then部分”。 - BigHead
1
@GongyuWang:没错。返回状态码为0表示成功;其他任何值都表示失败。Shell条件是成功与失败,而不是真与假。(/bin/true将退出状态设置为0;/bin/false将其设置为1。) - Keith Thompson
我觉得非常好奇的是,stderr重定向(2>/dev/null)实际上可以将命令行中的错误消息推送到文件中。我认为>> /tmp/bob重定向是命令行的一部分,而不是命令(:)的一部分。给你错误的东西不是:命令,而是整个命令行。相比之下,Zsh会告诉你重定向到/tmp/bob失败,无论你把2>/dev/null放在哪里。 - Ray

4
该脚本试图以不太明显的方式确保$outputFile可写。
bash中,:是空命令,它什么也不做。将stderr重定向到/dev/null仅是为了抑制权限被拒绝的错误,如果出现该错误,则命令失败。
如果文件不可写,则命令失败,由于使用了!取反,因此条件为真,脚本退出。

好的而且简明扼要的回答!谢谢。 - BigHead

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接