Что делает символ "|" в linux pipe? [Дубликат]

23

Вот команда, которая сортирует файлы в папке в обратном порядке

ls | sort -r

Что делает |символ в этой команде?

То, что я действительно ищу здесь, это объяснение каналов для начинающих Linux высокого уровня (легко понять). Я вижу другие вопросы о каналах здесь, на Superuser, но ничего, что дает ответ, который объясняет простыми словами, что они делают и чем они отличаются от перенаправления ( символ >или <).

ccalvert
источник
7
Это не имеет ничего общего с Linux (который является ядром). Каналы в целом являются средством переадресации ввода / вывода, в оболочке типа bash она ничем не отличается. Единственное, что особенного в a |- это то, что он не использует имя, вывод из команды l-hand передается непосредственно на вход для команды на правой стороне канала.
Андон М. Коулман
Для урока истории на эту тему прочитайте linfo.org/pipe.html
Фредрик Пихл
ls -1r(Обратите внимание на аргумент номер один) должен дать аналогичный результат ls | sort -r.
Иван Чау
Мне нравится объяснять это так: канал принимает выходные данные одной команды и делает ее пригодной для использования следующей командой. Например, вы можете сделать cat /somefile | grep cool. Это возьмет вывод somefile и сделает его доступным для grep, а затем grep напечатает все строки со словом cool в нем.
JohnDoea

Ответы:

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помощью некоторого загадочного синтаксиса, включающего амперсанды и скобки, о которых я не знаю.

LawrenceC
источник
Обратите внимание, что это не уникально для Linux или даже POSIX. Большинство (все?) Оболочек в Windows тоже делают это. И, вероятно, другие ОС.
Боб
Я знаю концепцию Windows stdinи stdoutотличается от нее по сравнению с Linux, хотя, вероятно, не очень с точки зрения Windows cmd.exeили Powershell.
LawrenceC
Мне очень любопытно, как это отличается - не могли бы вы объяснить? Может быть, в чате, если комментарии не подходят для этого.
Боб
1
Программы Win32 определенно имеют стандартный ввод и вывод. Например, вы можете получить стандартный ввод, вывод или обработчик ошибок вашего процесса с помощью функции Win32 GetStdHandle(). Кроме того, тривиально перенаправить стандартные потоки порожденного [дочернего] процесса с помощью .NET, который, как я считаю, соответствует функциям Win32 (но я не уверен на 100% - я не разработчик Win32).
Боб
1
Ах, вот эквивалент Win32, установив соответствующие параметры в STARTUPINFOструктуре для CreateProcess().
Боб
27

Если вас устраивает перенаправление вывода и ввода, объяснение действительно довольно простое.

Command1 | Command2

делает так же, как

Command1 > tempfile
Command2 < tempfile

но без tempfile. Выход Command1напрямую связан с входом Command2и передача происходит в памяти.

Даниэль Б
источник
Я могу ошибаться, но я думаю, что tempfile существует даже в синтаксисе канала. У него просто нет имени.
Taemyr
3
Нет. При передаче данных от одной команды к входу другой команды операции с файловой системой не выполняются.
Даниэль Б
1
Хотя под DOS (и , скорее всего , Windows), временный файл будет создан по трубе. Не * nix, но ничего не стоит разницы.
Джереми Дж. Старчер
Я уверен, что это не правильно. Process Monitor сообщает об отсутствии CreateFileили WriteFileзвонках, чтобы подтвердить вашу претензию. / edit: Это для Windows, конечно.
Даниэль Б
3

На самом деле, если вы хотите знать, что делают каналы, и разницу между> и |, перейдите в каталог с большим количеством файлов, и

из терминала ls против ls | more (или делать это из Windows с DIR и DIR | MORE)

Если вы использовали> more, вы увидите, что он создает файл с именем 'more', а не отправляет вывод ls в команду 'more'. Поэтому, если кто-то сделает> больше, это, вероятно, будет ошибкой, он не сделает> больше, чем вы бы сделали> file1. More - это хорошо известная команда.

<Like> также предназначен для связывания команды и файла, а не команды с командой. Но в то время как> отправляет вывод команды в файл, <отправляет файл в качестве ввода для команды. Я редко использую <, как я обычно использую cat file1 | отправить вывод файла в команду.

$ grep a <file1 abc

$ cat file1 | grep a abc

grep с 2 параметрами имеет вид файла шаблона grep. grep с одним параметром - это шаблон grep. И вы можете отправить ему файл, отправив по нему содержимое файла или используя <. Если вы используете <, вы сначала пишете имя команды, затем имя файла после команды <file. При использовании | чтобы передать содержимое файла, вы используете cat file1 | команда.

Также многие команды в любом случае принимают файл в качестве входных данных, поэтому grep file1 будет работать так же, как cat file1 | grep a и grep a <file1.

Я делал трубы (|) и> на DOS даже 15 лет назад.

Подводя итог, как | отличается от <и> - канал находится между 2 командами. <и> находятся между командой и файлом. > Выводится в файл. <Является вводом из файла.

barlop
источник
3

Символ pipe ( |) соединяет вывод одной программы со входом другой.

В этом примере echoпечатает слово helloи wc -cподсчитывает количество введенных символов:

echo hello | wc -c
bbaassssiiee
источник
Я думаю, вы должны сразу сказать, что echo выдаст "hello \ n". Вы не говорите ОП учиться, вы говорите это всем, кто читает ваш ответ. Зачем умножать эту трата времени?
Родриго
Спасибо за отзыв, я сократил свой ответ.
bbaassssiiee
2

Чтобы понять это, попробуйте сами:

sort -r

Теперь вы зависаете с курсором, и он ничего не делает. Что произойдет, если вы введете некоторые данные?

1
2
3
5
4

Все еще ничего, верно? Теперь нажмите Ctrl + D

5
4
3
2
1

Итак, что делает сортировка, она берет ввод (то, что вы ввели), что-то делает с ним (сортирует) и возвращает его в качестве вывода. Команда lsне принимает ввод, она только генерирует вывод. Символ канала принимает выходные данные lsи передает их в качестве входных данных для sortкоманды.

>не передает вывод в программу, но сохраняет вывод в виде файла. <использует файл в качестве входных данных.

jornane
источник