В чем различия между &> и 2>&1
Существует две формы перенаправления стандартного вывода и стандартной ошибки в стандартный вывод. Но какой из них лучше? и почему &>
считается идеальным?
Я не могу найти, в чем различия, так что многие учебники и даже руководство Bash заявляют, что &>
лучше!
Так почему я должен использовать &>
и не 2>&1
В основном с использованием bash
ракушка
РЕДАКТИРОВАТЬ: Спасибо за комментарии
Только>& работает в csh или tcsh
В ksh работает только 2>&1.
dash use> file 2>&1 redirection
Тогда какой из них использовать для обеспечения совместимости моего скрипта с другими системами, какими бы ни были используемые оболочки!
4 ответа
Страница руководства 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-подобных оболочек.
Смотрите также Что означает и что конкретно означает перенаправление вывода?
В общем, я бы рекомендовал следовать образу действий Bourne-again SHell, поскольку bash, пожалуй, самая популярная оболочка Unix. Bash обычно использует либо &>
или же 2>&1
, ИМХО, ни то, ни другое "идеально", поэтому я рекомендую забыть об этой ерунде. Реально, какой из них вы должны использовать, зависит от того, что вы пытаетесь сделать.
2>&1
объединяет stderr с stdout, что может быть полезно, если, например, вы хотите передать текст stderr. Так, например, если вы хотите увидеть, печатает ли программа определенное сообщение stderr, но не хотите, чтобы ваш экран заполнялся (предположительно) неважным мусором, вы можете сделать что-то вроде program 2>&1 | grep crashed
, который будет искать в stdout и stderr из программы под названием "program" слово "crash".
С другой стороны, если вы не хотите, чтобы программа вообще что-либо печатала, вы можете просто запустить 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
может быть более вероятно, работать на оболочках не Баш.
PS: если вы беспокоитесь о людях, использующих другие оболочки, есть что-то, что вы можете добавить в первую строку вашего сценария, называемое "магическим числом" или "шебанг". По сути, это способ убедиться, что другие компьютеры (особенно те, на которых работают Unix-подобные операционные системы) знают, какую программу использовать для выполнения скрипта. Разные сценарии используют разные шебанги. Шебанг для сценария bash выглядит так:
#!/bin/bash
Если вы используете вышеперечисленное в качестве первой строки данного скрипта, bash обычно будет использоваться для выполнения указанного скрипта. Это значительно усложнит случайное выполнение сценария с неверной оболочкой.
PS: я не собираюсь лгать: до сих пор я не знал, что можно использовать >&
, но, что касается Bash, похоже, делает то же самое, что &>
, Ты узнаешь что-то новое каждый день.
Так почему я должен использовать &> а не 2>&1
2>&1
стандартная оболочка Bourne/POSIX
&>
является расширением bash, а не стандартом де-юре.
Если вы пишете сценарии с использованием расширений bash, рано или поздно вы столкнетесь со сбоем в голове с зашифрованными сообщениями об ошибках синтаксиса, поскольку они запускаются в стандартной оболочке.
Из справочного руководства Bash -> 3.6.4 Перенаправление стандартного вывода и стандартной ошибки:
Эта конструкция позволяет перенаправлять как стандартный вывод (дескриптор файла 1), так и стандартный вывод ошибок (дескриптор файла 2) в файл, имя которого является расширением слова.
Существует два формата для перенаправления стандартного вывода и стандартной ошибки:
&>word
а также
>&word
Из двух форм первая является предпочтительной. Это семантически эквивалентно
>word 2>&1
При использовании второй формы слово не может расширяться до числа или "-". Если это так, применяются другие операторы перенаправления (см. Дублирование файловых дескрипторов ниже) по причинам совместимости.
Также полезно обратиться к вики Грега по вводу и выводу -> 4.2. Манипуляция дескриптором файла:
Для удобства Bash также предоставляет вам еще одну форму перенаправления. Оператор перенаправления &> на самом деле является просто более короткой версией того, что мы сделали здесь [
2>&1
]; перенаправить как stdout, так и stderr в файл.