Невозможно перенаправить на дескриптор файла, хранящийся в переменной
Примечание редактора: этот вопрос подвергся нескольким изменениям, которые изменили природу проблемы, что может сделать недействительными старые комментарии и ответы; его первоначальное название было "Невозможно перенаправить вывод Bash в /dev/null".
Я пытаюсь создать небольшой скрипт Bash, для которого я хотел бы реализовать тихий режим. По сути, я просто хотел бы скрыть большую часть вывода по умолчанию и, в случае, если я запускаю его с -v
покажи весь вывод.
Итак, в начале моего сценария я поставил:
#!/bin/bash
declare output=''
if [ "$1" = -v ]; then
output="&1"
else
output="/dev/null"
fi
Тогда в моих сценариях у меня есть:
{
# whatever commands...
} > $output 2>&1
Тихий режим работает хорошо. Однако, если я попробую подробный режим, файл с именем &
или же &1
(основываясь на моем output
переменная) создается. Также файл пуст. Это не желаемый результат: я хочу, чтобы вывод оставался на терминале!
Это из-за того, в каком порядке я перенаправляю или моя переменная неверна? РЕДАКТИРОВАТЬ: сценарий теперь работает полностью, заменив "&1"
в качестве выходного значения с "/dev/tty"
,
2 ответа
Скорее всего, выводится сообщение об ошибке. Обратите внимание, что с > /dev/null
только стандартный вывод перенаправлен, а стандартный - нет. Ты можешь использовать 2>&1
перенаправить stderr на стандартный вывод перед перенаправлением стандартного вывода. Что-то вроде:
{
# whatever commands...
} > $output 2>&1
ТЛ; др
Вы не можете хранить перенаправления в файловые дескрипторы (
&1
в вашем случае) в переменных - если вы это сделаете, вместо этого вы создадите файл с этим именем (файл с буквальным именем&1
в твоем случае).настройка
$output
в/dev/tty
не рекомендуется, потому что вы всегда выводите на терминал, что предотвращает захват подробного вывода в файл; например,script -v > file
не сработаетВоспользуйтесь gniourf_gniourf из комментариев и используйте
exec
вместо:exec > /dev/null 2>&1
или, используя специфичный для Bash синтаксис,exec &>/dev/null
заставляет замолчать оставшуюся часть сценария.
Перенаправление на файловый дескриптор работает только:
- если цель перенаправления является литералом, а не ссылкой на переменную.
- если между
>
и цель.
date > &1 # !! SYNTAX ERROR: syntax error near unexpected token `&'
date >&1 # OK - but works with a *literal* `&1` only
Если вы используетепеременную, это не имеет значения, потому что содержимое переменной неизменно интерпретируется как имя файла- поэтому вы не получили синтаксическую ошибку, а получили выходной файл с буквальным именем &1
вместо.
output='&1'
date >$output # !! Creates a *file* named '&1'.
date > $output # !! Ditto.
Чтобы решить вашу проблему, я предлагаю gniourf_gniourf советом gniourf_gniourf из комментариев: exec
вместо:
#!/usr/bin/env bash
if [[ $1 == '-v' ]]; then
: # verbose mode: redirect nothing
else
# quiet mode: silence both stdout and stderr
exec &>/dev/null
fi
echo 'hello' # will only print with -v specified
echo 'hello' >&2 # ditto