Intereting Posts
autossh -ND при загрузке Ubuntu Как я могу отменить «Прибытие событий из Календаря эволюции» в «Время и дата»? Как установить Ubuntu на Galaxy Nexus Как создать резервную копию моего ключа PGP Аккорды GnomeMplayer отображаются как «?», Как я это исправить? Как добавить пользовательские приложения / скрипты в приложения для запуска в 14.10? Может ли сочувствие быть настроенным, чтобы оставаться в курсе, будет ли полный разговор? Ошибки при попытке установить пакет default-jre-headless из диспетчера синаптических пакетов Не удалось найти пакет с помощью regex libstdc ++. So.5 libexpat.so.0 в 32-разрядном ubuntu 12.04 Измените непрозрачность выделения (nemo.css) Как я могу отключить экран в режиме ожидания? Можете ли вы изменить ориентацию пусковой установки Unity? разделительная строка с awk и разделителем Какие пакеты предоставляют изображенные апплеты гном-панели? Gparted: создание нового логического раздела

Захват stdout для переменной, но все же отображающий ее в консоли

У меня есть сценарий bash, который вызывает несколько длительных процессов. Я хочу записать вывод этих вызовов в переменные для обработки. Однако, поскольку это длительные процессы, я хотел бы, чтобы вывод вызовов rsync отображался на консоли в режиме реального времени, а не после факта.

С этой целью я нашел способ сделать это, но он полагается на вывод текста в / dev / stderr. Я чувствую, что вывод в / dev / stderr не является хорошим способом делать что-то.

VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee /dev/stderr) VAR2=$(rsync -r -t --out-format='%n%L' --delete -s /path/source1/ /path/target1 | tee /dev/stderr) VAR3=$(rsync -r -t --out-format='%n%L' --delete -s /path/source2/ /path/target2 | tee /dev/stderr) 

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

Есть ли «чистый» способ сделать это?

Если это имеет значение, я использую Ubuntu 12.04, bash 4.2.24.

Related of "Захват stdout для переменной, но все же отображающий ее в консоли"

Дублируйте & 1 в своей оболочке (в моем примере до 5) и используйте & 5 в подоболочке (чтобы вы записывали в stdout (& 1) родительской оболочки):

 exec 5>&1 FF=$(echo aaa|tee >(cat - >&5)) echo $FF 

Будет печатать aaa два раза, из-за эха в подоболочке и второй раз печатать значение переменной.

В вашем коде:

 exec 5>&1 VAR1=$(for i in {1..5}; do sleep 1; echo $i; done | tee >(cat - >&5)) # use the value of VAR1 

Ответ от Де Кирка имеет правильную идею. Его можно упростить еще больше (избегая использования cat ):

 exec 5>&1 FF=$(echo aaa|tee /dev/fd/5) echo $FF 

Ниже приведен пример захвата как stderr и кода выхода команды. Это строится на ответе Рассела Дэвиса.

 exec 5>&1 FF=$(ls /taco/ 2>&1 |tee /dev/fd/5; exit ${PIPESTATUS[0]}) exit_code=$? echo "$FF" echo "Exit Code: $exit_code" 

Если папка /taco/ существует, это запишет ее содержимое. Если папка не существует, она будет отображать сообщение об ошибке, а код выхода – 2.

Если вы опустите 2>&1 тогда будет снято только stdout .

Вы можете использовать более трех дескрипторов файлов. Попробуйте здесь:

http://tldp.org/LDP/abs/html/io-redirection.html

«Каждому открытому файлу присваивается файловый дескриптор. [2] Дескрипторы файлов для stdin, stdout и stderr равны 0, 1 и 2. Соответственно, для открытия дополнительных файлов остаются дескрипторы с 3 по 9. Иногда полезно назначьте один из этих дополнительных файловых дескрипторов для stdin, stdout или stderr как временную дублируемую ссылку. ”

Дело в том, стоит ли сделать сценарий более сложным, чтобы добиться этого результата. На самом деле это не совсем так, как вы это делаете.