将所有命令的输出重定向到文件,而不仅仅是最后一个


11

我想向带有回显的文件添加标头,然后使用命令创建文件的其余部分。这意味着我将使用两个单独的命令。

如何将两个命令的输出写入具有重定向的文件?

我试过了

echo "header line" | cut -c 1-5 input_file > output_file

echo "header line"; cut -c 1-5 input_file > output_file

这只会重定向cut命令的输出。

以下命令有效,但感觉笨拙:

echo "header line" > output_file; cut -c 1-5 input_file >> output_file

解决我的问题的聪明方法是什么?

Answers:


11

这里的问题与Linux重定向无关。相反,这是对管道如何工作的根本误解。重定向在这里不起作用,因为实际上只有剪切才能打印到stdout。echo命令的stdout已通过管道传递到cut的stdin(在这种情况下,因为指定了文件,所以未使用它)。

echo "header line" > output_file && cut -c 1-5 input_file >> output_file

是您想要的,并且一点都不优雅(我用替换了您;&&以便cut命令仅在成功写入标头时才执行;这样,如果您没有创建或写入output_file的权限,它将不会执行)。

您也可以在子shell中完成所有操作,例如。

(echo "header line"; cut -c 1-5 input_file) > output_file

但是这样做并没有真正的好处,如果您不熟悉subshel​​l的范围,那么使用更复杂的示例可能会导致问题。

如果要剪切将stdin传递到stdout,可以尝试:

echo "header line" | cut -c 1-5 - input_file

(破折号是stdin的常用快捷方式)

但是,这还将对stdin执行剪切操作(导致标题行为“ header”)。从问题中很难分辨出这是否是您想要的。


13

您寻找的是:

{ echo "header line"; cut -c 1-5 input_file; } > output_file
  • 该语法没有副作用,因为命令在当前外壳程序而不是子外壳程序中执行
  • 到output_file的命令有明确的界线
  • 它可以很好地扩展,您可以通过以下方式进行重写:

{
  echo "header line"
  cut -c 1-5 input_file
  ... # insert new commands here
} > output_file

如果您希望错误输出转到相同的文件,则可以这样修改最后一行:

} > output_file 2>&1

感谢Olivier Dulac提醒您该提示。

如果您希望块内的某些输出进入屏幕,则可以使用以下语法:

{
  echo "header line"
  echo "this line doesn't go to output_file" > /dev/tty
  cut -c 1-5 input_file
} > output_file

+1:更清晰,可以清楚地标识重定向到何处的内容。重定向所有内容(包括错误msg):({ .... } > some_file 2>&1将“ clobber” some_file。替换为不是clobber,而是附加到其上,只需将其更改>>>{ ... } >> some_file 2>&1
Olivier Dulac

4

只是为了完善答案,这里有exec。

exec > output_file
echo "header line"
cut -c 1-5 input_file

+1:在脚本中使用它是很常见的(在命令行上会少用,因为事情开始变得混乱^^)
Olivier Dulac

有人可以详细说明这个解决方案吗?我可以看到它在做什么,但是在这种情况下我不理解“ exec”。另外,如果脚本的其余部分需要正常的标准输出,则似乎必须再次关闭电源。

1
当您在不带命令的脚本中使用exec时,可以在exec上执行I / O重定向,这会影响当前的Shell和所有将来的子代。
hildred

谢谢。我以前没看过。我认为这将非常有用。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.