Передача по каналу вывода столбцов команды

Я использую lolcat для получения вывода ls в цвете. Чтобы сделать это, я скопировал/usr/bin/ls в/usr/bin/lsslss (для предотвращения бесконечного цикла, так как псевдоним не может принять $* или $), и я добавил функцию:

ls(){ lsslss $* | lolcat; } к .bashrc

Проблема - то, что, когда я использую ls, канал передается каждый файл по каналу за один раз, таким образом, он обнаруживается как длинный список как это:

enter image description here

вместо таблицы как это:

enter image description here

для изменения его в таблицу, я могу передать вывод по каналу в команду столбцов. но когда я делаю это возвращается в длинный список (вероятно, из-за столбцов, только форматирует его вместо того, чтобы изменить его в строки),

Я первоначально собирался сделать:

ls(){ lsslss $* | columns | lolcat; }

Так или иначе я задавался вопросом существует ли способ передать необработанный вывод по каналу вместо того, чтобы использовать |, чтобы смочь передать вывод по каналу столбцов в lolcat?

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

5
задан 20 May 2019 в 14:01

2 ответа

Подробно останавливаясь на ответе @dessert, Вам нужно немного больше работы для создания цветного ls версия ведет себя точно так же, как реальное ls в (надо надеяться?) все случаи. Проблема - это ls не предназначен, чтобы быть проанализированным, но предназначенным для человеческих глаз только. С этой целью это сильно адаптируется, как это работает в зависимости от среды, например, подключено ли это к терминалу или производящий к каналу.

Во-первых, Вам не нужно отдельное /bin/lsslss исполняемый файл для предотвращения рекурсии. Используйте встроенную оболочку command назвать исполняемый файл от диска, игнорируя любые функции оболочки или псевдонимы того же имени.

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

И треть, в зависимости от того, куда Вы помещаете определение, синтаксис ls () { ... ;} определить функцию не могло бы работать если ls уже псевдоним, потому что расширение псевдонима происходит сначала, вызывая синтаксическую ошибку. Используйте явный синтаксис путем записи function перед ним.

Затем мы можем использовать ls' -C отметьте для ручного включения вывода столбца:

function ls() { command ls -C "$@" | lolcat ;}

Однако, если мы просто делаем это и передаем вывод по каналу через lolcat (или что-либо еще), Вы заметите, что это не использует полную ширину Вашего терминала больше, но только 80 столбцов самое большее. Это вызвано тем, что это не может обнаружить терминальную ширину, если ее стандарт непосредственно больше не подключается к нему. Ваша оболочка все еще знает терминал, хотя, и это заполняет COLUMNS переменная с шириной это обнаружило. Но, поскольку эта переменная не экспортируется по умолчанию, ls не видит это значение. Мы можем вручную передать его только для этой команды как:

function ls() { COLUMNS="$COLUMNS" command ls -C "$@" | lolcat ;}

Теперь мы должны всегда получать корректную ширину, но что происходит, если мы действительно хотим передать по каналу ls через что-то еще? Обычно Вы не должны делать этого, потому что, поскольку я сказал в начале, ls никогда не должен анализироваться. Иногда это могло бы все еще быть полезно, хотя (и некоторые сценарии мог бы печально полагаться на него), поэтому давайте попытаемся, по крайней мере, сохранить исходное поведение затем. Прямо сейчас мы всегда получали бы столбцы, как произведено для, например. ls | cat. (Это больше не окрашивается там потому что lolcat также проверки, если это производит к терминалу или каналу и выключает цвета в последнем случае),

Давайте добавим проверку к нашей функции, которая использует реальную плоскость ls если это передается по каналу и наша необычная версия столбца радуги только для терминального представления. Является ли стандарт (дескриптор файла 1) terminal/TTY, может просто быть сверен [[ -t 1 ]]:

function ls() { 
    if [[ -t 1 ]] ; then COLUMNS="$COLUMNS" command ls -C "$@" | lolcat ; else command ls "$@" ; fi
}

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

14
ответ дан 20 May 2019 в 14:01

Когда его вывод передается по конвейеру, ls отключает список столбцов. Используйте опцию -C, чтобы явно включить ее:

ls(){ COLUMNS="$COLUMNS" command ls -C "$@" | lolcat; }

COLUMNS="$COLUMNS" устанавливает переменную COLUMNS в соответствии с шириной текущего терминала, без значения по умолчанию 80 - попробуйте изменить размер окна терминала и сравните выходы. command ls служит для игнорирования псевдонимов и функций и вызова ls везде, где находится его исполняемый файл. Обратите внимание, что я использовал "$@", чтобы процитировать вики Bash Hackers :

["$@"] отражает все позиционные параметры, которые были установлены изначально и переданы в скрипт или функция. Если вы хотите повторно использовать ваши позиционные параметры для вызова другой программы (например, в сценарии-обертке), то этот выбор для вас, используйте двойные кавычки "$@".
Хорошо, давайте просто скажем: Вы почти всегда хотите заключить в кавычки "$@"!

0
ответ дан 20 May 2019 в 14:01

Другие вопросы по тегам:

Похожие вопросы: