Вопрос: В чем разница между «перенаправлением» и «трубой»?


Этот вопрос может показаться немного глупым, но я не могу видеть разницу между перенаправлением и трубами.

Перенаправление используется для перенаправления stdout / stdin / stderr, например. ls > log.txt,

Трубы используются для вывода вывода команды в качестве входных данных для другой команды, например. ls | grep file.txt,

Но почему есть два оператора для одного и того же?

Почему бы просто не написать ls > grep чтобы передать выход, разве это не просто переадресация? Что мне не хватает?


166
2017-08-07 13:22


Источник




Ответы:


Труба используется для передачи вывода на другой программа или полезность,

Переадресация используется для передачи вывода на файл или поток,

Пример: thing1 > thing2 против thing1 | thing2

thing1 > thing2

  1. Ваша оболочка будет запускать программу с именем thing1
  2. Все что thing1 выходы будут помещены в файл, называемый thing2, (Примечание - если thing2 существует, он будет перезаписан)

Если вы хотите передать результат из программы thing1 к программе, называемой thing2, вы можете сделать следующее:

thing1 > temp_file && thing2 < temp_file

которые бы

  1. запустить программу с именем thing1
  2. сохраните вывод в файл с именем temp_file
  3. запустить программу с именем thing2, притворяясь, что человек на клавиатуре напечатал содержимое temp_file как вход.

Однако это неудобно, поэтому они сделали трубы более простым способом сделать это. thing1 | thing2 делает то же самое, что и thing1 > temp_file && thing2 < temp_file

EDIT, чтобы предоставить более подробную информацию на вопрос в комментарии:

Если > пытался «перейти к программе» и «написать в файл», это может вызвать проблемы в обоих направлениях.

Первый пример: Вы пытаетесь записать файл. Там уже существует файл с таким именем, которое вы хотите перезаписать. Однако файл является исполняемым. Предположительно, он попытается выполнить этот файл, передав вход. Вам нужно будет сделать что-то вроде записи вывода в новое имя файла, а затем переименуйте файл.

Второй пример: Как отметил Флориан Дёш, если есть другая команда в другом месте системы с тем же именем (то есть в пути выполнения). Если вы планируете создать файл с этим именем в текущей папке, вы застряли.

В-третьих: если вы неправильно написали команду, это не предупредит вас о том, что команда не существует. Прямо сейчас, если вы набираете ls | gerp log.txt он скажет вам bash: gerp: command not found, Если > означало и то и другое, оно просто создало бы для вас новый файл (тогда предупреждайте, что он не знает, что делать с log.txt).


189
2017-08-07 13:30



Спасибо. Ты упомянул thing1 > temp_file && thing2 < temp_file для облегчения работы с трубами. Но почему бы не повторить использование > оператора для этого, например. thing1 > thing2 для команд thing1 а также thing2 ? Почему дополнительный оператор | ? - John Threepwood
«Возьмите вывод и напишите его в файл» - это другое действие, чем «Возьмите вывод и передайте его в другую программу». Я отредактирую больше мыслей в свой ответ ... - David Oneill
@JohnThreepwood У них разные значения. Что делать, если я хочу перенаправить что-то в файл с именем less, например? thing | less а также thing > less совершенно разные, поскольку они делают разные вещи. То, что вы предлагаете, создало бы двусмысленность. - Darkhogg
Справедливо ли говорить, что «thing1> temp_file» является просто синтаксическим сахаром для «thing1 | tee temp_file»? Поскольку я узнал о тройнике, я почти никогда не использую перенаправления. - Sridhar-Sarnobat
@ Шридхар-Сарнобат нет, tee команда делает что-то другое. tee записывает вывод на экран (stdout) а также файл. Перенаправление только файл. - David Oneill


Если смысл foo > bar будет зависеть от того, есть ли команда с именем bar что сделало бы использование перенаправления намного сложнее и подвержено ошибкам: каждый раз, когда я хочу перенаправить файл, мне сначала нужно было проверить, есть ли команда, названная как мой файл назначения.


18
2017-08-07 13:40





Между двумя операторами существует существенное различие:

  1. ls > log.txt -> Эта команда отправляет результат в файл log.txt.

  2. ls | grep file.txt -> Эта команда отправляет вывод команды ls в grep через использование канала (|), а команда grep ищет файл file.txt во входном файле, предоставленном ему предыдущей командой.

Если вам пришлось выполнить одну и ту же задачу, используя первый сценарий, то это будет:

ls > log.txt; grep 'file.txt' log.txt

Итак, труба (с |) используется для отправки вывода в другую команду, тогда как перенаправление (с >) используется для перенаправления вывода в некоторый файл.


10
2017-08-07 13:32





В Руководстве по системному администрированию Unix и Linux:

Перенаправление

Оболочка интерпретирует символы <,> и >> как инструкции для перенаправления командования ввод или вывод в или из файл,

трубы

Чтобы подключить STDOUT одного команда к STDIN другой используйте | символ, обычно известный как труба.

Итак, моя интерпретация: если это команда для команды, используйте трубу. Если вы отправляете в или из файла, используйте перенаправление.


9
2018-02-16 00:40





Существует большая синтаксическая разница между ними:

  1. Переадресация - это аргумент для программы
  2. Труба разделяет две команды

Вы можете думать о таких переадресациях: cat [<infile] [>outfile], Это означает, что порядок не имеет значения: cat <infile >outfile такой же как cat >outfile <infile, Вы даже можете смешивать перенаправления с другими аргументами: cat >outfile <infile -b а также cat <infile -b >outfile оба прекрасно. Кроме того, вы можете объединять более одного ввода или вывода (входы будут считываться последовательно, и весь вывод будет записан в каждый выходной файл): cat >outfile1 >outfile2 <infile1 <infile2, Целевой или источник перенаправления может быть либо именем файла, либо именем потока (например, & 1, по крайней мере, в bash).

Но трубы полностью отделяют одну команду от другой команды, вы не можете смешивать их с аргументами:

[command1] | [command2]

Труба берет все, что записано на стандартный вывод из команды1, и отправляет его на стандартный ввод команды2.

Вы также можете комбинировать трубопроводы и перенаправление. Например:

cat <infile >outfile | cat <infile2 >outfile2

Первый cat будут читать строки из infile, затем одновременно записывать каждую строку в outfile и отправлять ее на второй cat,

В секунду cat, стандартный ввод сначала считывается из трубы (содержимое infile), затем считывается из infile2, записывая каждую строку в outfile2. После запуска outfile будет копией infile, а outfile2 будет содержать infile, за которым следует infile2.

Наконец, вы действительно делаете что-то действительно похожее на ваш пример, используя перенаправление «здесь строка» (только семейство bash) и обратные ссылки:

grep blah <<<`ls`

даст тот же результат, что и

ls | grep blah

Но я думаю, что версия перенаправления сначала будет считывать весь вывод ls в буфер (в памяти), а затем кормить этот буфер для grep по одной строке за раз, тогда как версия с каналами будет принимать каждую строку от ls по мере ее появления, и передать эту строку в grep.


2
2017-08-23 22:24



Nitpick: порядок имеет значение при перенаправлении, если вы перенаправляете один fd на другой: echo yes 1>&2 2>/tmp/blah; wc -l /tmp/blah; echo yes 2>/tmp/blah 1>&2; wc -l /tmp/blah Кроме того, перенаправление на файл будет использовать только последнее перенаправление. echo yes >/tmp/blah >/tmp/blah2 будет писать только /tmp/blah2, - muru
Перенаправление не является фактически аргументом для программы. Программа не знает и не заботится о том, куда идет ее выход (или поступает ввод). Это просто способ сообщить bash, как организовать вещи перед запуском программы. - Alois Mahdal


Сегодня я столкнулся с проблемой в C. По сути, у Труб есть и другая семантика для переадресации, даже если она отправляется stdin, Действительно, я думаю, учитывая различия, трубы должны идти куда-то, кроме stdin, так что stdin и позволяет называть его stdpipe (для произвольного дифференциала) можно обрабатывать по-разному.

Учти это. При прокладке одной программы на другую fstat кажется, возвращает ноль, поскольку st_sizeнесмотря ls -lha /proc/{PID}/fd показывая, что есть файл. При перенаправлении файла это не так (по крайней мере, на debian wheezy, stretch а также jessie ванили и ubuntu 14.04, 16.04 ваниль.

если ты cat /proc/{PID}/fd/0 с перенаправлением вы сможете повторять, чтобы читать столько раз, сколько захотите. Если вы сделаете это с помощью трубы, вы заметите, что во второй раз, когда вы выполняете задачу последовательно, вы не получите тот же результат.


1
2017-10-26 16:17





Чтобы добавить к другим ответам, есть и семантическая разность в подслоях. трубы закрываются более легко, чем перенаправления:

seq 5 | (head -n1; head -n1)                # just 1
seq 5 > tmp5; (head -n1; head -n1) < tmp5   # 1 and 2
seq 5 | (read LINE; echo $LINE; head -n1)   # 1 and 2

В первом примере, когда первый вызов head заканчивается, он закрывает трубу, и seq завершается, поэтому нет ввода для второго head,

Во втором примере голова потребляет первую строку, но когда она закрывает свою собственную stdin  труба, файл остается открытым для следующего вызова.

Третий пример показывает, что если мы используем read чтобы избежать закрытия трубы, он все еще доступен в рамках подпроцесса.

Таким образом, «поток» - это то, с чем мы шунтируем данные через (stdin и т. Д.) И одинаково в обоих случаях, но канал соединяет потоки из двух процессов, где перенаправление соединяет потоки между процессом и файлом, поэтому вы может видеть источник как сходства, так и различий.

Постскриптум Если вы так же любопытны и / или удивлены этими примерами, как и я, вы можете продолжить копать дальше trap чтобы увидеть, как процессы разрешаются, например:

(trap 'echo seq EXITed >&2' EXIT; seq 5) | (trap 'echo all done' EXIT; (trap 'echo first head exited' EXIT; head -n1)
echo '.'
(trap 'echo second head exited' EXIT; head -n1))

Иногда первый процесс закрывается раньше 1 печатается, иногда потом.

Мне также было интересно использовать exec <&- чтобы закрыть поток из перенаправления, чтобы приблизить поведение трубы (хотя и с ошибкой):

seq 5 > tmp5
(trap 'echo all done' EXIT
(trap 'echo first head exited' EXIT; head -n1)
echo '.'
exec <&-
(trap 'echo second head exited' EXIT; head -n1)) < tmp5`

1
2018-06-05 00:54