linux管道符号“ |”有什么作用?[重复]


23

这是一个以相反顺序对文件夹中的文件进行排序的命令

ls | sort -r

|该命令中的符号有什么作用?

我在这里真正要寻找的是针对Linux初学者的高级(易于理解)管道解释。我在Superuser上看到了有关管道的其他问题,但是没有一个问题可以用简单的术语来解释它们的作用以及它们与重定向(><符号)的区别。


7
这与Linux(内核)无关。通常,管道是一种重定向输入/输出的方法,在bash这样的shell中也是如此。关于a的唯一特殊之处|是它不使用名称,l-hand命令的输出直接传递到管道r-hand侧的命令输入。
安东·科尔曼

有关该主题的历史课程,请阅读linfo.org/pipe.html
Fredrik

ls -1r(请注意第一个参数)应产生与相似的结果ls | sort -r
Ivan Chau

我喜欢这样解释:管道接收一个命令的输出,并使其可用于后续命令。例如,您可以这样做cat /somefile | grep cool。这将获取somefile的输出并使其可用于grep,然后grep将在其中打印带有单词cool的所有行。
-JohnDoea

Answers:


26

以下内容进行了简化,以帮助新用户。

好吧,首先,有必要了解标准输入和标准输出的概念。

在Linux和其他类似UNIX的操作系统中,每个进程都有一个标准输入(stdin)和一个标准输出(stdout)。通常的情况是stdin您的键盘stdout是屏幕或终端窗口。

因此,当您运行时ls,它将把它的输出扔给stdout。如果您什么也不做,它将进入您的屏幕或终端窗口,您将对其进行查看。

现在,一些Linux命令与用户进行交互,并使用它stdin来执行操作,您的文本编辑器就是其中之一。它从读取stdin以接受您的击键,执行操作,然后将内容写入stdout

但是,也有非交互式或“过滤器”命令无法交互工作,但需要大量数据。这些命令将处理所有stdin已拥有的内容,对其执行某些操作,然后将其扔到stdout

让我们看看另一个命令du-代表磁盘使用情况。 du /usr,例如,将打印出(与stdout其他Linux命令一样)该目录中每个文件的列表及其大小:

# du /usr
2312    /usr/games
124     /usr/lib/tc
692     /usr/lib/rygel-1.0
400     /usr/lib/apt/methods
40      /usr/lib/apt/solvers
444     /usr/lib/apt
6772    /usr/lib/gnash

正如您可以立即得知的那样,它没有进行排序,您可能希望按大小顺序对其进行排序。

sort是那些“过滤器”命令之一,该命令将从其中收集大量内容stdin并对其进行排序。

因此,如果我们这样做:

# du /usr | sort -nr

我们得到了,这更好一些:

4213348 /usr
2070308 /usr/lib
1747764 /usr/share
583668  /usr/lib/vmware
501700  /usr/share/locale
366476  /usr/lib/x86_64-linux-gnu
318660  /usr/lib/libreoffice
295388  /usr/lib/vmware/modules
290376  /usr/lib/vmware/modules/binary
279056  /usr/lib/libreoffice/program
216980  /usr/share/icons

现在您可以看到“管道”将stdout一个命令的命令连接到另一个命令的命令stdin。通常,您将在需要过滤,排序或以其他方式处理命令输出的情况下使用它。如果要通过多个过滤器类型的命令处理输出,可以将它们级联。

如果您sort自行输入,它将仍然尝试从中读取stdin。由于stdin已连接到键盘,它将一直等您键入并处理内容,直到您按Control-D。它不会提示您,因为它并不是真正用于交互使用。

程序可能会判断是否stdin是交互式的,因此,如果您单独发布它们或在管道末端发布它们,则某些程序的行为可能有所不同。

另外,管道化只能以交互方式工作的程序(例如vi)将导致您的工作时间很短。

管道与重定向的不同之处在于,数据从一个命令移至下一个命令而没有存储在任何地方。因此,在以上示例中,du的输出未存储在任何地方。大多数情况下,您不希望使用管道,因为使用管道的原因是要以某种方式处理命令的输出-但是,有一条命令tee可以让您吃蛋糕也可以吃,将接收stdin到的信息复制到两者stdout以及您选择的文件中。您也可以bash使用一些我不知道的涉及&符号和方括号的奥术语法来完成此操作。


请注意,这并不是Linux甚至POSIX所独有的。Windows上的大多数(全部?)shell也会这样做。可能还有其他操作系统。
鲍勃

我知道Windows 的概念stdinstdoutLinux下的概念有所不同,尽管从Windows cmd.exe或Powershell 的角度来看可能并不多。
LawrenceC

我很好奇它有什么不同-您介意解释吗?如果评论不合适,也许可以聊天。
鲍勃

1
Win32程序绝对具有标准的输入和输出。例如,您可以使用Win32函数检索过程的标准输入,输出或错误句柄GetStdHandle()。用.NET重定向生成的[子]进程的标准流也很简单,我相信它映射到Win32函数(但我不是100%确信-我不是Win32开发人员)。
鲍勃

1
嗯,是Win32的等效项,方法是在STARTUPINFOstruct中设置适当的参数CreateProcess()
鲍勃

27

如果您对输出和输入重定向感到满意,那么说明非常简单。

Command1 | Command2

与...相同

Command1 > tempfile
Command2 < tempfile

但是没有tempfile。的输出Command1直接连接到的输入,Command2并且传输在内存中进行。


我可能是错的,但我认为临时文件即使在管道语法中也存在。它只是没有名字。
塔米尔(Taemyr),2014年

3
不,不是的。将一个命令的输出传递到另一命令的输入时,不涉及文件系统操作。
Daniel B

1
但是,在DOS(和Windows)下,管道创建一个临时文件。不是* nix,但没有任何区别。
杰里米·J·斯塔彻

我很确定这是不正确的。Process Monitor报告否,CreateFileWriteFile致电支持您的索赔。/ edit:当然,这是针对Windows的。
丹尼尔·B

3

真的,如果您想知道管道的作用以及>和|之间的区别,请转到包含大量文件的目录,然后

从终端 ls vs ls | more (或在带有DIR和DIR的Windows中执行此操作|更多)

如果使用> more,您会看到它创建了一个名为“ more”的文件,而不是将ls的输出发送到“ more”命令。因此,如果有人做的更多,那可能是一个错误,那么您将不会做的更多。More是一个众所周知的命令。

<like>也可用于链接命令和文件,而不是将命令链接到命令。但是,当>将命令的输出发送到文件时,<将文件作为输入发送到命令。我很少使用<,因为我通常使用cat file1 | 将文件的输出发送到命令。

$ grep a <file1 abc

$ cat file1 | grep abc

具有2个参数的grep格式为grep模式文件。具有一个参数的grep是grep模式。然后,您可以通过将文件内容传递给文件或使用<将文件发送给它。如果使用<,则先写命令名,然后在命令<文件名后写文件名。如果使用| 管道文件的内容,您可以使用cat file1 | 命令。

同样,许多命令仍然将文件作为输入,因此grep file1可以正常工作,就像cat file1 | cat一样。grep a和grep a <file1。

即使在15年前,我也在DOS上进行管道(|)和>。

总结如何| 与<和>不同- 管道位于2个命令之间<和>位于命令和文件之间。>将输出到文件。<是从文件输入的。


3

竖线字符(|)将一个程序的输出连接到另一个程序的输入。

在此示例中,echo输出单词hello,并wc -c对其输入进行字符计数:

echo hello | wc -c

我想您应该立即说回声将输出“ hello \ n”。您不是要告诉OP学习,而是告诉所有阅读您答案的人。为什么要增加这种浪费的时间?
罗德里戈

感谢您的反馈,我缩短了答案。
bbaassssiiee

2

为了了解这一点,请自己尝试:

sort -r

现在您正在用游标挂起,它什么也没做。如果您输入一些数据会怎样?

1
2
3
5
4

还是没事吧?现在按Ctrl + D

5
4
3
2
1

因此,排序是什么,它需要输入(您输入的内容),对其进行某种处理(排序),然后将其作为输出返回。该ls命令不接受输入,仅生成输出。管道符号从中获取输出ls,并将其作为sort命令的输入。

>不会将输出提供给程序,而是将输出存储为文件。<使用文件作为输入。

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.