Мое намерение состоит в том, чтобы вывести журнал рекурсивного wget
в одну строку, 'status bar'-like. Поэтому я собрал этот трубопровод (мой wget
вызов имеет немного больше вариантов, но я оставил тех, важно только для проблемы, описанной):Комплексный трубопровод bash работает в прыжках
wget -r -nv ftp://example.com 2>&1 | cut -c1-80 | xargs -I line echo -ne 'line\033[0K\r'
Позвольте мне объяснить, что я имел в виду сделать. Может быть, с моей командой что-то не так.
-r
означает «рекурсивная загрузка»;-nv
делает сообщения о каждой загрузке краткими, например: «time: URL -> local file»;- перенаправляет stderr на stdout, чтобы я мог работать с сообщениями через трубы;
| cut -c1-80
разрезает выходную линию до 80 символов. Иногда URL и локальное имя файла вместе образуют длинную строку, которая разбивает строку на 2 или более. И мне нужно, чтобы он вписывался в одну линию консоли. 80 стоит здесь, например. В моем сценарии я определяю ширину консоли сtput cols
;| xargs -I line echo -ne 'line\033[0K\r'
печатает выходные данные предыдущей команды и добавляет два специальных символа:\033[OK
- конец строки, который очищает остальную часть строки, если есть какие-либо символы, оставшиеся от выходов prevoius; и\r
- возврат каретки, который устанавливает курсор в начало текущей строки.
Так что разыскиваемый поведение:
wget
загружает файл и пытается распечатать уведомление об этом на стандартный выводcut
сразу перехватывает вывод Wget и обрезает его до 80 символовxargs
ловит обрезную линию и печатает ее немедленно со специальными символами
Поэтому я должен увидеть какую-то панель состояния, где отображается текущая загрузка.
Но! Все, что я вижу, ничего не происходит в течение 10-60 секунд, а затем все сообщения о загрузках, которые были сделаны за это время, печатаются примерно через 1 секунду. Они на самом деле печатали то, что я хотел, но очень быстро. Опять же, пауза, другая часть сообщений за 1 секунду и т. Д. Так что все хорошо, кроме сразу -ness.
Когда я удаляю часть xargs
, сообщения отображаются мгновенно (но не в одной строке). Когда я удаляю cut
звонок, они мгновенные, но иногда строка прерывается с некоторым действительно длинным URL-адресом. Если я удаляю только специальные символы от echo
, вызов выводится по-прежнему «прыгающим», а не в одной строке.
Для того, чтобы воспроизвести это, вы можете заменить ftp://example.com на любой URL (HTTP тоже будет работать), который можно использовать для тестирования рекурсивной загрузки, то есть в случае FTP имеет много файлов и каталогов и в случай HTTP имеет много ссылок на страницы, у которых больше ссылок (не бойтесь, что он может попытаться загрузить весь интернет, beacuse -r
имеет уровень рекурсии по умолчанию 5).Если вы не можете воспроизвести это, я полагаю, что это неправильно с моим дистрибутивом, пожалуйста, напишите об этом в разделе комментариев ниже.
P.S. Если вы знаете лучший способ организации строки состояния для wget
, ваши комментарии очень приветствуются. Но я изучаю Баша и хочу знать, что вызывает такое странное поведение. Может быть, есть что-то о трубах или echo
или xargs
Не знаю. Поэтому возникает вопрос, почему этот трубопровод работает так, а не так, как я ожидал.
Спасибо! Теперь я знаю, что вызвало проблему (буферизацию) и как обойти ее (awk). И да, xargs действительно не подходит для манипуляций строк. – Hnatt
Итак, в результате мой конвейер теперь выглядит так: 'wget -r -nv http://example.com 2> & 1 | awk -W interactive '{ORS = ""; print substr ($ 0,1,80) "\ 033 [0K \ r"} ''. '-W interactive' заставляет awks не выводить буфер, а' ORS = "" 'дает нам' print' без строк новой строки. – Hnatt