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

В моем script я хочу иметь возможность писать либо в файл, либо в stdout на основе определенных условий. Мне любопытно, почему это не работает в моем script:

out=\&1
echo "bird" 1>$out

Я пробовал различную комбинацию кавычек, но я продолжаю создавать файл "& 1" вместо записи в stdout. Что я могу сделать, чтобы заставить это работать, как я хочу?

Ответ 1

Возможно, более безопасная альтернатива eval заключается в том, чтобы объединить ваш пункт назначения во временный дескриптор файла, используя exec (дескриптор файла 3 в этом примере):

if somecondition; then exec 3> destfile; else exec 3>&1; fi

echo bird >&3

Ответ 2

Излагая ответ Диего. Чтобы изменить, где stdout идет условно

if [ someCondition ] ; then
  # all output now goes to $file
  exec 1>$file
fi

echo "bird"

Или создайте свой собственный дескриптор файла;

if [ someCondition ] ; then
  # 3 points to stdout
  exec 3>&1
else
  # 3 points to a file
  exec 3>$outfile
fi

echo "bird" >&3

Адаптировано из: программирование csh считается вредоносным - проверьте его на наличие других трюков перенаправления. Или прочитайте справочную страницу bash.

Ответ 3

С 2015 года можно перенаправить на >&${out}. Например.

exec {out}>&1
echo "bird" 1>&${out}

Ответ 4

Я почти уверен, что это связано с порядком, в котором bash обрабатывает командную строку. Следующие работы:

export out=\&1
eval "echo bird 1>${out}"

потому что замена переменной происходит до оценки.

Ответ 5

Попробуйте с eval. Он должен работать, интерпретируя значение самого $out:

out='&1'
eval "echo \"bird\" 1>$out"

Будет напечатан bird на стандартном выходе (и в файле, если вы измените out).

Обратите внимание, что вы должны быть осторожны с тем, что входит в строку eval. Обратите внимание на обратную косую черту с внутренними кавычками и что переменная $out должна быть замещена (с помощью двойных кавычек) до выполнения eval.