我正在学习基本的终端命令。
为什么这个命令没有按照我预期的那样工作?
echo "hello" >&0 | > file.txt
我知道我可以简单地打字echo "hello" > file.txt
,但我正在学习使用管道。我只想将单词“hello”输出到文件中。
答案1
在 bash 中,带有重定向的空命令只会以与重定向相关的方式打开文件,然后关闭它*。是一个由两个简单命令, ,echo "hello" >&0 | > file.txt
组成的复合命令。第二个命令是空的,因此 bash 只会打开文件进行写入、截断它,然后关闭它。echo "hello" >&0
> file.txt
在终端中,通常标准输入、输出和错误都连接到终端。因此,当您将 stdout 重定向到 stdin 时,它仍然指向终端,并且的输出echo hello >&0
在终端中可见,并且根本不发送到管道。
在 zsh 中,带有重定向的空命令默认为cat
命令。因此echo "hello" >&0 | > file.txt
实际上是echo "hello" >&0 | cat > file.txt
,您将看到想要的效果。这在 bash 中是不可能的。在这里,您将看到 bash 中没有的另一个重定向功能:当您多次重定向命令的输出时,输出将发送到每个重定向目的地(因此将hello
同时发送到终端和管道)。在 bash 中,它仅发送到最后一个重定向位置。
* 例外情况是命令替换使用重定向的标准输入。在 中$(<some-file)
,bash 将读取 的内容some-file
并将其用作命令替换的值。
答案2
啊,我明白你在想什么了(我想)。你试过了
echo hello | > file
并且什么也没发生file
,所以你想,也许我需要通过重定向将命令的输出转换为标准输入:
echo hello >&0
但将 stdout 转换为 stdin 正是管道所做的。它获取 stdout 并将其作为 stdin 传递给其右侧的命令。如果重定向 stdout,则不会通过管道传输任何内容:
$ echo hello >&0 | cat > file
hello
$ cat file
$
(空空如也)
但是hello
在终端中,它像往常一样从标准输入读取:
$ cat /dev/fd/0
hi
hi
I am talking to myself!
I am talking to myself!
等等...
如果我们不重定向...
$ echo hello | cat > file
$ cat file
hello
的标准echo hello
输出通过管道(而不是到终端)并成为的标准输入cat
。
因此,管道会执行您想要执行的操作(将 stdout 转换为 stdin 并将其连接到正确的命令),您不必通过摆弄文件描述符来自己完成这些操作。
至于为什么带有重定向的空命令不能完成您想要的操作,参见 muru 的回答。
答案3
我猜您也想将输出写入文件和标准输出。
echo hello > file.txt
部分执行此操作,但它会跳过标准输出(不会在控制台上打印任何内容)。如果您也想要这样做,请使用tee
以下命令:
echo hello | tee file.txt
它将 的输出通过管道传输echo
到 的输入tee
,然后 tee 将内容写入屏幕并写入 file.txt 中。
如果您只想打印到文件,请使用cat
以下命令:
echo hello | cat >file.txt
另请查看此答案以了解重定向的工作原理:https://stackoverflow.com/a/818265/5771279
管道的工作原理如下:https://stackoverflow.com/a/9834118/5771279
也查看tee
命令的手册页。
答案4
- 该
>
符号用于将文件重定向至文件开头。 - 该
>>
符号用于将文件重定向到文件末尾(附加)。 该
|
符号表示“管道”或将一个命令的输出作为另一个命令的输入传递。$ echo "Hello" > file.txt $ echo "World!" >> file.txt $ cat file.txt Hello World! $ cat file.txt | grep ! World!
(全局正则表达式打印)命令grep
在文件中搜索给定的搜索字符串并打印其所在的行。
根据&>0
高级 Bash 脚本指南:
&>filename
# Redirect both stdout and stderr to file "filename."
# This operator is now functional, as of Bash 4, final release.
在您的例子中,文件名是 0,即标准输入。因此它将所有输出重定向到输入。据我所知,这是一个无法正常工作的循环引用。您使用的语法是>&0
将输出重定向到输入。这似乎也是一个循环引用。
“文件名”为:
0
标准输入1
标准输出2
标准错误输出
通过文件重定向使用文件描述符(标准输入)的传统方式0
是:
0< FILENAME
< FILENAME
# Accept input from a file.
# Companion command to ">", and often used in combination with it.
#
# grep search-word <filename
如果您想一起使用echo
命令和|
(正如 Zanna 的回答指出的那样),您可以使用:
$ echo "hello" | cat > file.txt
$ cat file.txt
hello