В чем различия между &> и 2> & 1

30

Существует две формы перенаправления стандартного вывода и стандартной ошибки в стандартный вывод . Но какой из них лучше? а почему то &>считается идеальным?

Я не могу найти, в чем различия, так что многие руководства и даже руководство по bash указывают, что &>лучше!

Так почему я должен использовать, &>а не2>&1

В основном с использованием bashоболочки


РЕДАКТИРОВАТЬ: Спасибо за комментарии

Только> & работает в csh или tcsh

В ksh работает только 2> & 1.

dash use> file 2> & 1 redirection

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

Maythux
источник
лучше то, что делает то, что вам нужно сделать. они делают очень разные вещи. какую оболочку вы используете?
Skaperen
@Skaperen, используя bash
Maythux
1
что ты хочешь достичь?
Skaperen
Я просто хочу знать, в чем различия, что я хочу, так это не то и другое, но мне просто нужно знать, есть ли разница, чтобы однажды преобладать над другой
Maythux
2
&> somewhereэто просто сокращение от bash > somewhere 2>&1: по словам руководства bash, они «симметрично эквивалентны»
steeldriver

Ответы:

23

На странице руководства Bash упоминается, что существует два способа перенаправления stderr и stdout : &> file и >& file. Теперь обратите внимание, что это говорит и stderr и stdout.

В этом случае >file 2>&1мы выполняем перенаправление stdout (1) в файл, а затем говорим, что stderr (2) следует перенаправить в то же место, что и stdout! Так что цель может быть одна и та же, но идея немного другая. Другими словами "Джон, иди в школу; Сьюзи, иди туда, куда идет Джон".

А как насчет предпочтений? &>это bashвещь. Так что, если вы переносите скрипт, он этого не сделает. Но если вы на 100% уверены, что ваш скрипт будет работать только в системе с bash - тогда нет никаких предпочтений

Вот пример с dashоболочкой Debian Amquist, которая используется по умолчанию в Ubuntu.

$ grep "YOLO" * &> /dev/null
$ grep: Desktop: Is a directory
grep: Documents: Is a directory
grep: Downloads: Is a directory
grep: Music: Is a directory
grep: Pictures: Is a directory
grep: Public: Is a directory
grep: Templates: Is a directory
grep: Videos: Is a directory
grep: YOLO: Is a directory
grep: bin: Is a directory

Как видите, stderr не перенаправляется

Чтобы исправить изменения в вопросе, вы можете использовать оператор if для проверки переменной $ SHELL и изменения перенаправлений соответственно.

Но для большинства случаев > file 2>&1должно работать


В более технических терминах форма [integer]>&wordназывается Дублирование дескриптора выходного файла и является функцией, определяемой стандартом POSIX Shell Command Language, который поддерживается большинством POSIX-совместимых и Brourne-подобных оболочек.

Смотрите также Что означает и что конкретно означает перенаправление вывода?

Сергей Колодяжный
источник
Что происходит при использовании других оболочек?
Maythux
zsh поддерживает &>.... @Maythux В оболочках, которые не поддерживают, &>например, dashвам нужно использовать тривиальное >file 2>&1перенаправление ..
heemayl
Тогда какой из них использовать, если я хочу быть уверенным, что мой сценарий будет совместим с различными оболочками
Maythux
3
@Maythux Use >file 2>&1. Эта работа на всех снарядах
Сергей Колодяжный
1
@ TSJNachos117 оболочки, установленные /etc/passwdдля каждого пользователя, являются интерактивными оболочками. Системные сценарии обычно предназначены для, dash если не указано иное. Что касается того, что по умолчанию, это определяется тем, что символически связано с делом в /bin/shUbuntu dash. В RHEL это есть bash, во FreeBSD это tcsh источник и еще один источник
Сергей Колодяжный
7

В общем, я бы рекомендовал следовать образу действий Bourne-again SHell , поскольку bash, пожалуй, самая популярная оболочка Unix. Bash обычно использует либо &>или 2>&1. ИМХО, ни то, ни другое "идеально", поэтому я рекомендую забыть об этой ерунде. Реально, какой из них вы должны использовать, зависит от того, что вы пытаетесь сделать.

2>&1объединяет stderr с stdout, что может быть полезно, если, например, вы хотите передать текст stderr. Так, например, если вы хотите увидеть, печатает ли программа определенное сообщение stderr, но не хотите, чтобы ваш экран заполнялся (предположительно) неважным мусором, вы можете сделать что-то вроде этого program 2>&1 | grep crashed, который будет искать stdout и stderr из программы называется "программа" для слова "разбился".

С другой стороны, если вы не хотите, чтобы программа вообще что-либо печатала, вы можете просто запустить program &> /dev/null, что перенаправит и stderr, и stdout в / dev / null, специальный файл, который волшебным образом заставляет вещи исчезнуть. Или, если вы хотите сохранить выходные данные программы (возможно, сообщить об ошибке или что-то в этом роде), вы можете перенаправить как stderr, так и stdout в файл: program &> log.txtперенаправит все данные в файл с именем «log.txt». Если вы хотите, вы можете перенаправить stdout и stderr через program 2> log.txt > log.txtили program 2>&1 | cat > log.txt, оба из которых будут иметь тот же эффект, что и при использовании &>. Если вы сделаете что-то подобное program 2>&1 > file, будет перенаправлен только stdout, но stderr все еще может быть передан другой программе, например, cat, которую можно перенаправить, как показано выше. Тем не менее, набрав&>это проще, чем в любом из приведенных выше примеров, поскольку включает в себя ввод меньшего количества символов (и людям немного легче читать). Обратите внимание, что это program 2> log.txt > log.txtможет с большей вероятностью работать на оболочках, отличных от bash.

PS: если вы беспокоитесь о людях, использующих другие оболочки, есть что-то, что вы можете добавить в первую строку вашего сценария, называемое «магическим числом» или «шебанг». По сути, это способ убедиться, что другие компьютеры (особенно те, на которых работают Unix-подобные операционные системы) знают, какую программу использовать для выполнения скрипта. Разные сценарии используют разные шебанги. Шебанг для сценария bash выглядит так:

#!/bin/bash

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

PS: я не собираюсь лгать: до сих пор я не знал, что можно использовать >&, но, что касается bash, похоже, он делает то же самое, что и &>. Ты узнаешь что-то новое каждый день.

TSJNachos117
источник
Хотя я согласен с вами по поводу использования #!строки для явного запроса bash, она не всегда доступна в других системах. Очень часто разработчикам / системным администраторам приходится писать переносимые сценарии для систем, на которых они bashмогут быть недоступны, а установка может быть не под их контролем bash. Это >file 2>&1просто очень портативный.
Сергей Колодяжный
Вы допустили ошибку отмены, приведенную выше, которая не приводит к желаемому результату. Перенаправить stderr в stdout, затем перенаправить stdout, оставив stderr в исходном stdout.
ubfan1
Serg: Я не хотел сказать, что bash был универсальным. Тем не менее, я думаю, что больше людей используют его, чем сказать (т) CSH. Если вы не знаете, что использует кто-то другой, и должны делать слепые предположения, bash - это, вероятно, ваш лучший выбор. Кроме того, я вообще не знаю о переносимости, так как я использую только bash. Тот факт, что >file 2>&1он более портативный, это хорошо знать. Я сделаю правку, чтобы отразить это.
TSJNachos117
Ubfan1, спасибо за информацию. Я бы никогда не догадался за миллион лет, что bash не перенаправит stderr в файл в этом случае. Я только что отредактировал свой ответ, чтобы другие не совершили ту же ошибку.
TSJNachos117
4

Из справочного руководства Bash -> 3.6.4 Перенаправление стандартного вывода и стандартной ошибки :

Эта конструкция позволяет перенаправлять как стандартный вывод (дескриптор файла 1), так и стандартный вывод ошибок (дескриптор файла 2) в файл, имя которого является расширением слова.

Существует два формата для перенаправления стандартного вывода и стандартной ошибки:

&>word

а также

>&word

Из двух форм первая является предпочтительной. Это семантически эквивалентно

>word 2>&1

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

Также полезно обратиться к вики Грега по вводу и выводу -> 4.2. Манипуляция дескриптором файла :

Для удобства Bash также предоставляет вам еще одну форму перенаправления. Оператор перенаправления &> на самом деле является лишь краткой версией того, что мы здесь сделали [ 2>&1]; перенаправить как stdout, так и stderr в файл.

fedorqui
источник
4

Так почему я должен использовать &> а не 2> & 1

2>&1 стандартная оболочка Bourne / POSIX

&>является расширением bash, а не стандартом де-юре .

Если вы пишете сценарии с использованием расширений bash, рано или поздно вы столкнетесь со сбоем в голове с зашифрованными сообщениями об ошибках синтаксиса, поскольку они запускаются в стандартной оболочке.

Стивен М. Уэбб
источник