В оболочке, что делает & quot; 2 & amp; 1 " имею в виду?

В оболочке Unix, если я хочу объединить stderr и stdout в поток stdout для дальнейшей манипуляции, я могу добавить следующее в конец моей команды:

2>&1

Итак, если я хочу использовать head на выходе из g++, я могу сделать что-то вроде этого:

g++ lots_of_errors 2>&1 | head

, поэтому я вижу только первые несколько ошибок.

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

Может кто-то разбить это и объяснить символ за символом, что означает 2>&1?

вопрос задан 3.05.2009
Tristan Havelick
22959 репутация

15 ответов


  • 1992 рейтинг

    Файловый дескриптор 1 является стандартным выводом (stdout).
    Файловый дескриптор 2 является стандартной ошибкой (stderr).

    Вот один из способов запомнить эту конструкцию (хотя она не совсем точна): сначала 2>1 может выглядеть как хороший способ перенаправления stderr на stdout. Однако на самом деле это будет интерпретироваться как «перенаправление stderr в файл с именем 1». & указывает, что ниже приводится дескриптор файла, а не имя файла. Таким образом, конструкция становится: 2>&1.

    ответ дан Ayman Hourieh, с репутацией 84055, 3.05.2009
  • 494 рейтинг
    echo test > afile.txt
    

    перенаправляет стандартный вывод на afile.txt. Это то же самое, что и

    echo test 1> afile.txt
    

    Чтобы перенаправить stderr, вы делаете:

    echo test 2> afile.txt
    

    >& - это синтаксис для перенаправления потока на другой файловый дескриптор - 0 - это стандартный ввод, 1 - стандартный вывод, а 2 - стандартный вывод.

    Вы можете перенаправить стандартный вывод в stderr, выполнив:

    echo test 1>&2 # or echo test >&2
    

    или наоборот:

    echo test 2>&1
    

    Итак, вкратце. , , 2> перенаправляет stderr в файл (не указан), добавляя &1 перенаправляет stderr в стандартный вывод.

    ответ дан dbr, с репутацией 115348, 3.05.2009
  • 261 рейтинг

    Некоторые хитрости о перенаправлении

    Некоторые особенности синтаксиса могут иметь важные особенности. Есть несколько небольших примеров о перенаправлениях, STDERR, STDOUT и аргументах , заказывающих .

    1 - Перезаписать или добавить?

    Символ > означает перенаправление .

    • > означает, что отправлять в виде всего завершенного файла , перезаписывая цель, если она существует (см. Функцию bash noclobber в # 3 позже).
    • >> означает, что отправка в дополнение к добавится к цели, если существует.

    В любом случае файл будет создан, если он не существует.

    2 - Командная строка оболочки зависит от порядка! !

    Для проверки этого нам нужна простая команда , которая отправит что-то на оба выхода :

    $ ls -ld /tmp /tnt
    ls: cannot access /tnt: No such file or directory
    drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp
    
    $ ls -ld /tmp /tnt >/dev/null
    ls: cannot access /tnt: No such file or directory
    
    $ ls -ld /tmp /tnt 2>/dev/null
    drwxrwxrwt 118 root root 196608 Jan  7 11:49 /tmp
    

    (конечно, если у вас нет каталога с именем /tnt;). Ну, у нас это есть! !

    Итак, посмотрим:

    $ ls -ld /tmp /tnt >/dev/null
    ls: cannot access /tnt: No such file or directory
    
    $ ls -ld /tmp /tnt >/dev/null 2>&1
    
    $ ls -ld /tmp /tnt 2>&1 >/dev/null
    ls: cannot access /tnt: No such file or directory
    

    Последняя командная строка выводит STDERR на консоль, и это, кажется, не ожидаемое поведение. , , Но. , ,

    Если вы хотите выполнить некоторую пост-фильтрацию для одного выхода, другого или обоих:

    $ ls -ld /tmp /tnt | sed 's/^.*$/<-- & --->/'
    ls: cannot access /tnt: No such file or directory
    <-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->
    
    $ ls -ld /tmp /tnt 2>&1 | sed 's/^.*$/<-- & --->/'
    <-- ls: cannot access /tnt: No such file or directory --->
    <-- drwxrwxrwt 118 root root 196608 Jan  7 12:02 /tmp --->
    
    $ ls -ld /tmp /tnt >/dev/null | sed 's/^.*$/<-- & --->/'
    ls: cannot access /tnt: No such file or directory
    
    $ ls -ld /tmp /tnt >/dev/null 2>&1 | sed 's/^.*$/<-- & --->/'
    
    $ ls -ld /tmp /tnt 2>&1 >/dev/null | sed 's/^.*$/<-- & --->/'
    <-- ls: cannot access /tnt: No such file or directory --->
    

    Обратите внимание, что последняя командная строка в этом абзаце точно такая же, как и в предыдущем абзаце, где я написал , похоже, не является ожидаемым поведением (поэтому это может быть даже ожидаемое поведение).

    Ну, есть небольшие хитрости о перенаправлениях, для выполняет разные операции на обоих выходах :

    $ ( ls -ld /tmp /tnt | sed 's/^/O: /' >&9 ) 9>&2  2>&1  | sed 's/^/E: /'
    O: drwxrwxrwt 118 root root 196608 Jan  7 12:13 /tmp
    E: ls: cannot access /tnt: No such file or directory
    

    Примечание: &9 дескриптор возникнет самопроизвольно из-за ) 9>&2.

    Приложение: nota! С новой версией (>4.0) появилась новая функция и более привлекательный синтаксис для таких действий:

    $ ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /')
    O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
    E: ls: cannot access /tnt: No such file or directory
    

    И, наконец, для такого каскадного форматирования вывода:

    $ ((ls -ld /tmp /tnt |sed 's/^/O: /' >&9 ) 2>&1 |sed 's/^/E: /') 9>&1| cat -n
         1  O: drwxrwxrwt 118 root root 196608 Jan  7 12:29 /tmp
         2  E: ls: cannot access /tnt: No such file or directory
    

    Приложение: nota! Тот же новый синтаксис, обоими способами:

    $ cat -n <(ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /'))
         1  O: drwxrwxrwt 17 root root 28672 Nov  5 23:00 /tmp
         2  E: ls: cannot access /tnt: No such file or directory
    

    Где STDOUT проходят через определенный фильтр, STDERR - к другому и, наконец, оба слитых выхода проходят через третий фильтр команд.

    3 - Слово о опции noclobber и синтаксис >|

    Это примерно , перезаписывающий :

    В то время как set -o noclobber дают команду bash на , а не , перезаписывают любой существующий файл, синтаксис >| позволяет вам преодолеть это ограничение:

    $ testfile=$(mktemp /tmp/testNoClobberDate-XXXXXX)
    
    $ date > $testfile ; cat $testfile
    Mon Jan  7 13:18:15 CET 2013
    
    $ date > $testfile ; cat $testfile
    Mon Jan  7 13:18:19 CET 2013
    
    $ date > $testfile ; cat $testfile
    Mon Jan  7 13:18:21 CET 2013
    

    Файл каждый раз перезаписывается, ну теперь:

    $ set -o noclobber
    
    $ date > $testfile ; cat $testfile
    bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
    Mon Jan  7 13:18:21 CET 2013
    
    $ date > $testfile ; cat $testfile
    bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
    Mon Jan  7 13:18:21 CET 2013
    

    Пройдите с >|:

    $ date >| $testfile ; cat $testfile
    Mon Jan  7 13:18:58 CET 2013
    
    $ date >| $testfile ; cat $testfile
    Mon Jan  7 13:19:01 CET 2013
    

    Отключение этой опции и / или запрос, если он уже установлен.

    $ set -o | grep noclobber
    noclobber           on
    
    $ set +o noclobber
    
    $ set -o | grep noclobber
    noclobber           off
    
    $ date > $testfile ; cat $testfile
    Mon Jan  7 13:24:27 CET 2013
    
    $ rm $testfile
    

    4 - Последний трюк и многое другое. , ,

    Для перенаправления как вывода из данной команды, мы видим, что правильный синтаксис может быть:

    $ ls -ld /tmp /tnt >/dev/null 2>&1
    

    для этого особого случая , существует сокращенный синтаксис: &>. , , или >&

    $ ls -ld /tmp /tnt &>/dev/null
    
    $ ls -ld /tmp /tnt >&/dev/null
    

    Примечание: если 2>&1 существует, 1>&2 также является правильным синтаксисом:

    $ ls -ld /tmp /tnt 2>/dev/null 1>&2
    

    4b- Теперь я дам вам подумать:

    $ ls -ld /tmp /tnt 2>&1 1>&2  | sed -e s/^/++/
    ++/bin/ls: cannot access /tnt: No such file or directory
    ++drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/
    
    $ ls -ld /tmp /tnt 1>&2 2>&1  | sed -e s/^/++/
    /bin/ls: cannot access /tnt: No such file or directory
    drwxrwxrwt 193 root root 196608 Feb  9 11:08 /tmp/
    

    4c- Если вы заинтересованы в больше информации

    Вы можете прочитать прекрасное руководство, нажав:

    man -Len -Pless\ +/^REDIRECTION bash
    

    в консоли ;-)

    ответ дан F. Hauri, с репутацией 33584, 29.04.2013
  • 71 рейтинг

    Числа относятся к дескрипторам файлов (fd).

    • Ноль stdin
    • Один stdout
    • Два это stderr

    2>&1 перенаправляет FD 2 на 1.

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

    Вы можете посмотреть на /usr/include/unistd.h, если вы их забудете:

    /* Standard file descriptors.  */
    #define STDIN_FILENO    0   /* Standard input.  */
    #define STDOUT_FILENO   1   /* Standard output.  */
    #define STDERR_FILENO   2   /* Standard error output.  */
    

    Тем не менее, я написал инструменты C, которые используют нестандартные файловые дескрипторы для пользовательского ведения журнала, поэтому вы не увидите его, если не перенаправите его в файл или что-то еще.

    ответ дан Colin Burnett, с репутацией 7801, 3.05.2009
  • 52 рейтинг

    Я нашел этот блестящий пост о перенаправлении: Все о перенаправлениях

    Перенаправить стандартный вывод и стандартную ошибку в файл

    $ command & amp; & gt; file

    Этот однострочник использует оператор &> для перенаправления обоих потоков вывода - stdout и stderr - из команды в файл. Это ярлык Bash для быстрого перенаправления обоих потоков в одно и то же место.

    Вот как выглядит таблица дескрипторов файлов после того, как Bash перенаправил оба потока:

    Enter image description here

    Как видите, и stdout, и stderr теперь указывают на file. Таким образом, все, что написано в stdout и stderr, записывается в file.

    Существует несколько способов перенаправить оба потока в один и тот же пункт назначения. Вы можете перенаправить каждый поток один за другим:

    $ command & gt; file 2 & gt; & 1

    Это гораздо более распространенный способ перенаправления обоих потоков в файл. Сначала stdout перенаправляется в файл, а затем stderr дублируется, чтобы быть таким же, как stdout. Таким образом, оба потока в конечном итоге указывают на file.

    Когда Bash видит несколько перенаправлений, он обрабатывает их слева направо. Давайте пройдемся по шагам и посмотрим, как это происходит. Перед выполнением каких-либо команд таблица дескрипторов файлов Bash выглядит следующим образом:

    Enter image description here

    Теперь Bash обрабатывает первый файл перенаправления & gt ;. Мы видели это раньше, и это указывает на стандартный вывод в файл:

    Enter image description here

    Далее Bash видит второе перенаправление 2 & gt; & 1. Мы не видели этого перенаправления раньше. Этот дубликат файлового дескриптора 2 является копией файлового дескриптора 1, и мы получаем:

    Enter image description here

    Оба потока были перенаправлены в файл.

    Однако будьте осторожны здесь! Написание

    команда & gt; файл 2 & gt; & 1

    - это не то же самое, что запись:

    $ command 2 & gt; & 1 & gt; file

    Порядок перенаправлений имеет значение в Bash! Эта команда перенаправляет только стандартный вывод в файл. Stderr все еще будет печатать на терминал. Чтобы понять, почему это происходит, давайте снова пройдемся по шагам. Поэтому перед запуском команды таблица дескрипторов файлов выглядит следующим образом:

    Enter image description here

    Теперь Bash обрабатывает перенаправления слева направо. Сначала он видит 2 & gt; & amp; 1, поэтому дублирует stderr на stdout. Таблица дескрипторов файлов становится:

    Enter image description here

    Теперь Bash видит второе перенаправление, >file, и перенаправляет стандартный вывод в файл:

    Enter image description here

    Вы видите, что здесь происходит? Stdout теперь указывает на файл, но stderr по-прежнему указывает на терминал! Все, что записывается в stderr, все равно выводится на экран! Так что будьте очень, очень осторожны с порядком перенаправлений!

    Также обратите внимание, что в Bash пишется

    $ command & amp; & gt; file

    точно так же, как:

    $ command & gt; & amp; file

    ответ дан Deen John, с репутацией 957, 29.10.2016
  • 50 рейтинг

    Эта конструкция отправляет стандартный поток ошибок (stderr) в текущее местоположение стандартного вывода (stdout) - эта проблема с валютой, похоже, игнорировалась другими ответами.

    Вы можете перенаправить любой выходной дескриптор другому, используя этот метод, но чаще всего он используется для направления потоков stdout и stderr в один поток для обработки.

    Некоторые примеры:

    # Look for ERROR string in both stdout and stderr.
    foo 2>&1 | grep ERROR
    
    # Run the less pager without stderr screwing up the output.
    foo 2>&1 | less
    
    # Send stdout/err to file (with append) and terminal.
    foo 2>&1 |tee /dev/tty >>outfile
    
    # Send stderr to normal location and stdout to file.
    foo >outfile1 2>&1 >outfile2
    

    Обратите внимание, что последний будет , а не , прямой stderr на outfile2 - он перенаправляет его на то, что было stdout, когда аргумент был встречен (outfile1) и , тогда перенаправляет stdout на outfile2.

    Это позволяет довольно хитрый обман.

    ответ дан paxdiablo, с репутацией 612896, 3.05.2009
  • 14 рейтинг

    2>&1 - это конструкция оболочки POSIX. Вот разбивка, токен по токену:


    2: дескриптор выходного файла « Standard error ».

    >&: Дублировать оператор дескриптора выходного файла (вариант Перенаправление вывода оператор >). Учитывая [x]>&[y], дескриптор файла, обозначенный x, сделан как копия дескриптора выходного файла y.

    1 " Стандартный вывод " Дескриптор выходного файла.

    Выражение 2>&1 копирует дескриптор файла 1 в расположение 2, поэтому любой вывод, записанный в 2 («стандартная ошибка») в среде выполнения, попадает в тот же файл, который первоначально был описан в 1 («стандартный вывод»).


    Дополнительное объяснение:

    Дескриптор файла : «Уникальное неотрицательное целое число для процесса, используемое для идентификации открытого файла с целью доступа к файлу. "

    Стандартный вывод / ошибка : см. Следующее примечание в разделе «Перенаправление перенаправления» документации оболочки:

    Открытые файлы представлены десятичными числами, начинающимися с нуля. Максимально возможное значение определяется реализацией; однако все реализации должны поддерживать по крайней мере от 0 до 9 включительно для использования приложением. Эти числа называются «файловыми дескрипторами». Значения 0, 1 и 2 имеют особое значение и обычное использование и подразумеваются определенными операциями перенаправления; они называются стандартным вводом, стандартным выводом и стандартной ошибкой соответственно. Программы обычно берут свой ввод из стандартного ввода и записывают вывод в стандартный вывод. Сообщения об ошибках обычно пишутся со стандартной ошибкой. Операторам перенаправления может предшествовать одна или несколько цифр (без использования промежуточных символов) для обозначения номера дескриптора файла.

    ответ дан wjordan, с репутацией 10238, 25.12.2016
  • 12 рейтинг

    2 - стандартная ошибка консоли.

    1 - стандартный вывод консоли.

    Это стандартный Unix, и Windows также следует POSIX.

    E. г. когда вы запускаете

    perl test.pl 2>&1
    

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

    perl test.pl > debug.log 2>&1
    

    После выполнения вы можете увидеть все выходные данные, включая ошибки, в отладке. журнал.

    perl test.pl 1>out.log 2>err.log
    

    Тогда стандартный вывод идет на выход. журнал и стандартная ошибка, чтобы ошибаться. журнал.

    Я предлагаю вам попытаться понять это.

    ответ дан Marcus Thornton, с репутацией 2933, 19.07.2013
  • 12 рейтинг

    Чтобы ответить на ваш вопрос: он берет любой вывод ошибок (обычно отправляется в stderr) и записывает его в стандартный вывод (stdout).

    Это полезно, например, для «more», когда вам требуется подкачка для всего вывода. Некоторым программам нравится печатать информацию об использовании в stderr.

    Чтобы помочь вам вспомнить

    • 1 = стандартный вывод (где программы выводят нормальный вывод)
    • 2 = стандартная ошибка (где программы печатают ошибки)

    "2 & gt; & amp; 1" просто указывает все, что отправлено на stderr, вместо этого на stdout.

    Я также рекомендую прочитать этот пост об ошибке перенаправления , где эта тема рассматривается полностью.

    ответ дан Andrioid, с репутацией 2118, 3.05.2009
  • 10 рейтинг

    С точки зрения программиста, это означает именно это:

    dup2(1, 2);
    

    См. Справочную страницу .

    Понимание того, что 2>&1 является копией , также объясняет почему. , ,

    command >file 2>&1
    

    . , , это не то же самое, что. , ,

    command 2>&1 >file
    

    Первый отправит оба потока на file, а второй отправит ошибки на stdout, а обычный вывод на file.

    ответ дан ams, с репутацией 18300, 3.12.2015
  • 4 рейтинг

    Это похоже на передачу ошибки на стандартный вывод или в терминал.

    То есть cmd не является командой:

    $cmd 2>filename
    cat filename
    
    command not found
    

    Ошибка отправляется в файл, как это:

    2>&1
    

    Стандартная ошибка отправляется на терминал.

    ответ дан Kalanidhi, с репутацией 3294, 11.10.2013
  • 4 рейтинг

    При условии, что /foo не существует в вашей системе, а /tmp

    $ ls -l /tmp /foo
    

    распечатает содержимое /tmp и напечатает сообщение об ошибке для /foo

    $ ls -l /tmp /foo > /dev/null
    

    отправит содержимое /tmp в /dev/null и напечатает сообщение об ошибке для /foo

    $ ls -l /tmp /foo 1> /dev/null
    

    будет делать то же самое (обратите внимание на 1 )

    $ ls -l /tmp /foo 2> /dev/null
    

    распечатает содержимое /tmp и отправит сообщение об ошибке /dev/null

    $ ls -l /tmp /foo 1> /dev/null 2> /dev/null
    

    отправит как листинг, так и сообщение об ошибке /dev/null

    $ ls -l /tmp /foo > /dev/null 2> &1
    

    - стенография

    ответ дан Matijs, с репутацией 2538, 1.09.2016
  • 4 рейтинг

    Люди, всегда помните paxdiablo Намек о текущем местоположении цели перенаправления. , , Это важно.

    Моя личная мнемоника для оператора 2>&1 такая:

    • Думайте о & как о значении 'and' или 'add' (символ 3230269583 ампер - и , не так ли? )
    • Таким образом, это становится: 'перенаправить 2 (stderr) туда, где 1 (стандартный вывод) уже / в настоящее время и добавить оба потока' .

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

    • Подумайте о &, что означает and или add. , , (вы поняли насчет амперсанда, да? )
    • Так получается: 'перенаправить 1 (stdout) туда, где 2 (stderr) уже / в настоящее время и добавить оба потока' .

    И всегда помните: вы должны читать цепочки перенаправлений «с конца», справа налево (, а не слева направо).

    ответ дан Kurt Pfeifle, с репутацией 62066, 1.07.2012
  • 2 рейтинг

    Перенаправляющий ввод

    Перенаправление ввода вызывает файл с именем результаты раскрытия слова, которое нужно открыть для чтения в файле дескриптор n или стандартный ввод (дескриптор файла 0), если n не указан.

    Общий формат для перенаправления ввода:

    [n]

    Перенаправление вывода

    Перенаправление вывода вызывает файл, чей имя происходит от расширения слова, которое будет открыто для записи на дескриптор файла n или стандартный вывод (дескриптор файла 1), если n не указано Если файл не существует, он создается; если оно существует, он усекается до нулевого размера.

    Общий формат для перенаправления вывода:

    [n]>word
    

    Перемещение дескрипторов файлов

    Оператор перенаправления,

    [n]<&digit-
    

    перемещает цифру дескриптора файла в дескриптор файла n или стандартный ввод (дескриптор файла 0), если n не указано. цифра закрывается после дублирования на n.

    Аналогично, оператор перенаправления

    [n]>&digit-
    

    перемещает цифру дескриптора файла в дескриптор файла n или стандартный вывод (дескриптор файла 1), если n не указано.

    Ref:

    man bash
    

    Введите /^REDIRECT, чтобы найти раздел redirection, и узнайте больше. , ,

    Онлайн версия здесь: 3. 6 перенаправлений

    PS:

    Много времени man был мощным инструментом для изучения Linux.

    ответ дан yurenchen, с репутацией 369, 6.06.2015
  • 0 рейтинг

    0 для ввода, 1 для стандартного вывода и 2 для стандартного ввода.

    Один совет : somecmd >1.txt 2>&1 правильно, а somecmd 2>&1 >1.txt - полностью неправильно без эффекта!

    ответ дан fzyzcjy, с репутацией 1573, 25.07.2016