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

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

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

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


person Milo    schedule 04.11.2010    source источник
comment
Ваша система поддерживает out = / dev / stdout?   -  person mob    schedule 05.11.2010


Ответы (5)


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

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

echo bird >&3
person Sean    schedule 05.11.2010
comment
@Dennis: Я действительно не могу понять это клише eval ... Кажется, я заполняю все вопросы, связанные с bash, в stackoverflow :) И снова в тысячный раз: eval - это инструмент, а не риск сам по себе ... Это например, вы должны избегать Lisp, потому что вы можете рассматривать данные Lisp как код ... - person Diego Sevilla; 05.11.2010
comment
@Diego: eval может быть полезным инструментом. Это также представляет серьезные потенциальные риски для безопасности. Если вы этого избежите, вам не придется беспокоиться об этом конкретном наборе рисков. Часто этого легко избежать. По возможности выбирайте легкий и безопасный маршрут. Когда вы все же используете eval, убедитесь, что он вам действительно нужен, и что вы правильно дезинфицируете ввод и предпринимаете другие необходимые шаги для предотвращения проблем. См. BashFAQ / 048 и это отличный вопрос SO (за и против). Также обратите внимание, что я сказал, что лучше избегать, никогда не использовать. - person Dennis Williamson; 05.11.2010
comment
@Dennis: Я согласен с большей частью того, что вы говорите об общем использовании eval. Но в этом случае он контролирует весь код. Нет смысла избегать использования eval в коде, который я полностью контролирую ... - person Diego Sevilla; 06.11.2010
comment
@Diego: Зачем вам использовать eval в этом случае, когда exec чище и легче читается? Я считаю, что @Dennis указывает на то, что вы должны использовать eval только тогда, когда нет четкой альтернативы. В этом случае есть альтернатива получше. - person jabbie; 12.03.2011
comment
У меня возникли проблемы с тем, чтобы заставить это работать в моем собственном скрипте, вот синтаксис, который мне по какой-то причине пришлось использовать: destfile="/some/path"; exec 3>${destfile} - person Eliot; 02.05.2014

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

exec {out}>&1
echo "bird" 1>&${out}
person chutz    schedule 01.04.2015

Излагая ответ Диего. Чтобы условно изменить место вывода 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.

person jabbie    schedule 05.11.2010
comment
У меня возникли проблемы с тем, чтобы это работало в моем собственном скрипте, мне по какой-то причине пришлось использовать полную нотацию расширения переменных, например: destfile="/some/path"; exec 3>${destfile} - person Eliot; 02.05.2014

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

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

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

person paxdiablo    schedule 05.11.2010

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

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

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

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

person Diego Sevilla    schedule 05.11.2010