В чем разница между &> и >& в bash?

Вопрос или проблема

В чем разница между &> и >& в bash?

tldp не упомянул последний. Это действительно оператор перенаправления?

Или кто-то знает более полный учебный материал?

С страницы bash man:

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

          &>word
   и
          >&word

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

          >word 2>&1

Прочитайте раздел перенаправления страницы man bash.

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

man bash говорит

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

       &>word
и
       >&word

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

       >word 2>&1

Другие ответы не упомянули несколько оговорок, когда цитируют руководство:

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

&>word
и

>&word

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

>word 2>&1

А именно, очень важный факт, что:

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

Это подразумевает, что если вы хотите, чтобы имя файла, в который вы перенаправляете, было числом, вам лучше использовать первый формат (т.е. &>).

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

# Не сработает
echo hello >& '1' # Уходит в stdout, вместо файла с именем 1
echo hello >& "1" # Тоже самое.
echo hello >& \1  # Тоже самое.
echo hello >& $(echo 1) # Вы угадали... Bash умный!

# Успех
echo hello &> 1   # Ах, наконец, файл с именем 1 содержит "hello"

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

Также не забывайте, что нет такого оператора, как &| – только оператор |& существует для перенаправления stdout/stderr через пайп – еще одна причина использовать первый формат вместо второго, кроме случаев, когда вы не можете.

Я думаю, что это своего рода проблема X Y и что большинство читателей действительно хотят знать “что мне использовать: &> или >&?”, поэтому я отвечу на этот вопрос здесь.

Несмотря на то, что другие ответы цитируют страницу bash man, которая говорит “&> предпочтительнее”, я хотел бы ответить: это просто ваше мнение, человек. [цитата мема] На мой взгляд, нет, &> определенно не предпочтительно, потому что оно не работает в других оболочках (что показано ниже). Так что сделайте себе (и всем будущим пользователям ваших скриптов) одолжение и просто используйте >&.

Чтобы проиллюстрировать это, давайте посмотрим, что произойдет в zsh, если мы используем 1&>2 (с намерением перенаправить дескриптор файла 1 на 2):

$ echo "hello, stderr" 1&>2
$ ls
2
$ cat 2
hello, stderr

Как вы можете видеть, это записало “hello, stderr” в файл с именем 2.

(Обратите внимание, что вы также могли бы использовать echo "hello, stderr" &>2 здесь; 1 будет подразумеваться. Я привожу это для обучающих целей.)

Далее, &> даже не работает, если вы поместите его в скрипт вот так:

#!/bin/bash
echo "hello, stderr" 1&>2

Когда я вызвал этот скрипт из оболочки zsh, это записывало в файл с именем 2, несмотря на #!/bin/bash. Серьезная ловушка “работает на моем компьютере”, которая может произойти. (И да, я сталкивался с этим как с ошибкой несколько раз, и нет, это не легко диагностировать.)

Если вы хотите записать stdout в файл с именем 2, то просто сделайте:

echo "hello, stderr" 1>2

Это потому, что в переносимой POSIX оболочке перенаправление fd-to-fd происходит с помощью >&, а перенаправление fd-to-file происходит с помощью >. Сделайте себе одолжение и забудьте о существовании &>. Или, другими словами, “>& предпочтителен“.

Ответ или решение

Разница между &> и >& в Bash

Bash — это мощная командная оболочка, поддерживающая разнообразные механизмы перенаправления ввода и вывода. Среди них — синтаксисы &> и >&, которые используются для перенаправления стандартного вывода и стандартного потока ошибок. В этом ответе мы подробно рассмотрим различия между этими операторами.

Основные определения

  • &>: Этот оператор перенаправляет как стандартный вывод (stdout), так и стандартный поток ошибок (stderr) в указанный файл. Например:

    командa &> файл.txt

    В результате стандартный вывод и ошибки команды будут записаны в файл.txt.

  • >&: Этот оператор также используется для перенаправления, но его применение несколько отличается. Он более универсален и часто используется для перенаправления одного файлового дескриптора на другой. Например:

    команда 2>&1

    Здесь мы перенаправляем stderr (дескриптор 2) на stdout (дескриптор 1).

Операторы и их использование

  1. &>word:

    • Предпочитаемый синтаксис для перенаправления как stdout, так и stderr в один и тот же файл.
    • Если указать название файла (word), то правого аргумента может быть только имя файла, а не число или знак -.
    • Применяется так:
      echo "Hello" &> output.txt
  2. >&word:

    • Используется для перенаправления дескрипторов.
    • Могут возникнуть проблемы, если word будет интерпретировано как число или -. Это обусловлено тем, что Bash пытается использовать его в качестве дескриптора.
    • Например, данная команда:
      echo "Hello" >&2

      перенаправляет stdout (дескриптор 1) на stderr (дескриптор 2).

Важные различия

  • Семантика: Оператор &> подходит для отправки и стандартного вывода, и ошибок в файл, в то время как >& используется для перенаправления между файловыми дескрипторами.

  • Безопасность имён: Используя &> вы избегаете ситуации, когда имя файла может быть интерпретировано как дескриптор. Например, команда echo "Hello" >& 1 создаст файл 1, однозначно интерпретируя 1 как текст, а не как файловый дескриптор.

  • Совместимость: Оператор &> — это расширение Bash, поэтому его использование в других оболочках, таких как Zsh, может вызвать неожиданные результаты. В отличие от этого, >& соответствует стандартам POSIX и более совместим с другими оболочками.

Заключение

Чтобы обеспечить максимальную совместимость и избежать путаницы, рекомендуется использовать &> для перенаправления вывода и ошибок в файл, так как данный синтаксис проще и менее подвержен ошибкам. В случае же перенаправления потоков данных между дескрипторами следуйте оператору >&. Это поможет вам избежать неприятностей с именами файлов и повысить читаемость ваших скриптов.

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

Оцените материал
Добавить комментарий

Капча загружается...