Вопрос или проблема
В чем разница между &>
и >&
в 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).
Операторы и их использование
-
&>word
:- Предпочитаемый синтаксис для перенаправления как stdout, так и stderr в один и тот же файл.
- Если указать название файла (
word
), то правого аргумента может быть только имя файла, а не число или знак-
. - Применяется так:
echo "Hello" &> output.txt
-
>&word
:- Используется для перенаправления дескрипторов.
- Могут возникнуть проблемы, если
word
будет интерпретировано как число или-
. Это обусловлено тем, что Bash пытается использовать его в качестве дескриптора. - Например, данная команда:
echo "Hello" >&2
перенаправляет stdout (дескриптор 1) на stderr (дескриптор 2).
Важные различия
-
Семантика: Оператор
&>
подходит для отправки и стандартного вывода, и ошибок в файл, в то время как>&
используется для перенаправления между файловыми дескрипторами. -
Безопасность имён: Используя
&>
вы избегаете ситуации, когда имя файла может быть интерпретировано как дескриптор. Например, командаecho "Hello" >& 1
создаст файл1
, однозначно интерпретируя1
как текст, а не как файловый дескриптор. -
Совместимость: Оператор
&>
— это расширение Bash, поэтому его использование в других оболочках, таких как Zsh, может вызвать неожиданные результаты. В отличие от этого,>&
соответствует стандартам POSIX и более совместим с другими оболочками.
Заключение
Чтобы обеспечить максимальную совместимость и избежать путаницы, рекомендуется использовать &>
для перенаправления вывода и ошибок в файл, так как данный синтаксис проще и менее подвержен ошибкам. В случае же перенаправления потоков данных между дескрипторами следуйте оператору >&
. Это поможет вам избежать неприятностей с именами файлов и повысить читаемость ваших скриптов.
Для лучшего понимания перенаправления ввода и вывода в Bash, обратитесь к официальной документации Bash или к man bash
, где представлен более полный разбор.