管道和重定向与析取、连接等的绑定优先级?

管道和重定向与析取、连接等的绑定优先级?

我知道运算符;, &, &&, 或||的相对绑定优先级bash 文档

但是,当管道与我一起出现时,&&我很难理解绑定强度,要么偶然发现正确的命令,要么干脆放弃。

|>上述相比,其绑定优先级是什么?

我感到困惑的例子:

ls _thumbnails/video.mp4.jpg 2>/dev/null 
    && echo "thumbnail already generated. Not regenerating" \
    && exit \
    || ffmpeg_thumbnail_create video.mp4 2>/dev/null \
    && ls _thumbnails/video.mp4.jpg \
    && echo "Thumbnail successfully created" \
    && exit \
    || echo "Thumbnail creation failed" \
    | tee ~/thumbnails.log

上述的目标是当且仅当缩略图尚不存在时创建缩略图(我每天运行一个 cronjob)。而且我不喜欢 FFMpeg 在没有错误的情况下的大量输出(这不是 Unix 方式)。

还有其他情况,因此使用单独的语句或特定于这些程序的特殊选项的建议不会有帮助 - 我想了解绑定优先级。

答案1

简而言之<, 、>、 及其变体具有最高的绑定优先级(最紧绑定),其次|&&、 和||;&。因此,只有echo "Thumbnail creation failed"被通过管道输送到tee.

一个稍长的答案会指出最高优先级实际上就是分组,可以用括号或大括号来表示。例如,

A  &&  (B; C)

A  &&  { B; C;}

大约相当于

if A
then
    B
    C
fi

笔记:

  • 括号给你一个子shell;即命令BC在子进程中运行。因此,诸如变量赋值或之类的命令cd 不会对父 shell 产生任何影响。大括号中的命令与该命令在同一进程中运行A。因此,大括号结构A && { B; C;}更接近if- then-else结构。
  • 在大括号语法中,有必须是 后面的空格{和 之前的 a ;(或&或换行符)}

如需进一步阅读,请参阅shell 的控制和重定向运算符是什么?什么时候不需要“如果”?(特别是我的答案)。

为了进一步阅读,请参阅bash(1) 手册页Shell 命令语言的 POSIX 规范/定义, 具体来说第 2.9 节, Shell 命令部分 2.10.2, Shell 语法规则。这是试图为上述内容提供一些背景:

  • myVar=42
  • IFS= read a
  • date
  • cd /some/directory
  • ls -laR dir1 dir2
  • cat foo* > /tmp/allfoo
  • ls -laR dir{1,2}
  • find . -type f -name "foo*" -print > /tmp/output 2> /dev/null
  • > newfile
  • [ -f catfood ]
  • exit

都被认为是“简单命令”。

    • 简单命令1  |  简单命令2  |  简单命令3
    是“管道”。语法建立构建块并在其上构建,就像这样的正式语法(以及像 C 这样的编程语言)一样,因此单个“简单命令”被认为是“管道”,即使它不包含管道。变量赋值作为管道的组成部分没有(语义)意义,但像x=1 | od -ab或 之类的东西ls -laR | z=0在语法上是有效的。
    • 管道1  &&  管道2  ||  管道3
    bash 称为“列表”,POSIX 称为“AND-OR 列表”。同样,单个“管道”甚至单个“简单命令”都被视为“AND-OR 列表”,即使它不包含 AND 或 OR。
  • 当你遇到类似的事情时
      与或列表1 &  与或列表2 ;  与或列表3
    命名法开始变得有点不一致。 Bash 也将这些称为“列表”; POSIX 称它们为“列表”、“复合列表”和(很少)“术语”。同样,单个“AND-OR 列表”、“管道”甚至单个“简单命令”都被视为“列表”,即使它不包含&或一个;
    • (化合物列表
    { 化合物列表;}
流程控制命令(`for`、`if`-`then`-`else`、`while` 等)称为“复合命令”。 

在上面的示例中,将AB、 和解释C为管道可能是最有意义的。请记住,“管道”可以是单个“简单命令”;它不需要包含管道。

相关内容