Bash Shell保存多个命令的输出

你想用重定向获得输出,但是在一行中输入了多个命令:

pwd; ls; cd ../elsewhere; pwd; ls > /tmp/all.out

末尾的重定向仅应用于最后那个 ls 命令。其他命令的输出依旧出现在屏幕上(并未被重定向)。

解决方案

使用花括号({})将这些命令组合在一起,然后将重定向应用于分组中所有命令的输出。例如:

{ pwd; ls; cd ../elsewhere; pwd; ls; } > /tmp/all.out

这里有两个不易察觉的细微之处。花括号实际上是保留字,因此两侧必须有空白字符。另外,闭合花括号之前的拖尾分号也是不能少的。

或者,你也可以用括号(())告诉 bash 在子 shell 中运行这些命令,然后重定向整个子 shell 的输出。例如:

(pwd; ls; cd ../elsewhere; pwd; ls) > /tmp/all.out

讨论

尽管这两种解决方案看起来差不多,但存在两处重要的区别。第一处是语法上的,第二处是语义上的。从语法上来看,花括号两侧需要有空白字符,命令列表中的最后一个命令必须以分号结尾。如果使用括号,那就不要求这些了。更大的区别在于语义方面,也就是这些构件所代表的含义。花括号只是一种组合多个命令的方式而已,更像是重定向的便捷写法,这样我们就不用单独重定向各个命令了。而出现在括号中的命令是在 shell 的另一个实例中运行,也就是当前 shell 的子 shell。

子 shell 几乎复刻了当前 shell 的环境,包括 $PATH 在内的变量都是一模一样的,但对陷阱的处理有所不同。采用子 shell 方法的重大不同在于:因为 cd 命令是在子 shell 中执行的,所以退出子 shell 后,父 shell 的当前目录仍保持原样,shell 变量也不会发生变化。

如果使用花括号分组命令,最后你会位于一个全新的目录中(这个示例为 ../elsewhere)。你所做的其他改动(如变量赋值)也会应用于当前 shell。虽然两种方法会获得相同的输出,但最终所在的目录位置大不相同。

花括号有一种值得注意的用法,即能够形成更简洁的分支语句块。你可以缩短下列语句:

if [ $result = 1 ]; then
    echo "Result is 1; excellent."
    exit 0
else
    echo "Uh-oh, ummm, RUN AWAY! "
    exit 120
fi

精简成:

[ $result = 1 ] \
  && { echo "Result is 1; excellent." ; exit 0; } \
  || { echo "Uh-oh, ummm, RUN AWAY! " ; exit 120; }

采用哪种写法取决于你的个人风格以及对可读性的理解,但我们推荐第一种形式,这种写法更清晰,适合更大范围的受众。

酷客网相关文章:

赞(0)

评论 抢沙发

评论前必须登录!