Передача выходных данных столбцов команд
Я использую lolcat, чтобы получить вывод цвета ls. Для этого я скопировал /usr/bin/ls в /usr/bin/lsslss (чтобы избежать бесконечного цикла, поскольку псевдоним не может принимать $* или $@), и я добавил функцию:
ls(){ lsslss $* | lolcat; }
в.bashrc
Проблема в том, что когда я использую ls, канал передается каждому файлу за раз, поэтому он отображается в виде длинного списка:
вместо таблицы как это:
чтобы преобразовать его в таблицу, я могу передать вывод команды в столбцы. но когда я это делаю, он снова превращается в длинный список (вероятно, из-за того, что столбцы только форматируют его, а не превращают в строки)
Я изначально собирался сделать:
ls(){ lsslss $* | columns | lolcat; }
В любом случае, мне было интересно, есть ли способ передать исходный вывод вместо использования | быть в состоянии направить вывод столбцов в lolcat?
Заранее спасибо. Извините, если мой вопрос плохо сформулирован или его трудно понять. Я почти всегда нахожу вопросы, которые уже задавались, поэтому я не часто публикую вопросы.
2 ответа
Разбираясь с ответом @ десерт, вам нужно немного больше работы, чтобы сделать ваш цветной 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
если это по трубопроводу и наша необычная версия радуги столбец только для просмотра терминала. Является ли стандарт out (файловый дескриптор 1) терминалом /TTY, можно просто проверить с помощью [[ -t 1 ]]
:
function ls() {
if [[ -t 1 ]] ; then COLUMNS="$COLUMNS" command ls -C "$@" | lolcat ; else command ls "$@" ; fi
}
Я думаю, что этого должно хватить, чтобы поймать все случаи, когда особое / отличное поведение от ls
ожидается, так что ваша функция добавляет цвет только при просмотре непосредственно в терминале и в противном случае ничего не меняет.
Когда его вывод по трубопроводу, ls
отключает список столбцов. Использовать -C
возможность явно включить его:
ls(){ COLUMNS="$COLUMNS" command ls -C "$@" | lolcat; }
COLUMNS="$COLUMNS"
устанавливает COLUMNS
Правильно изменяйте ширину текущего терминала, без значения по умолчанию 80 - попробуйте изменить размер окна терминала и сравните выходные данные. command ls
служит для игнорирования псевдонимов и функций и вызова ls
везде, где его исполняемый файл. Обратите внимание, что я использовал "$@"
Процитирую Bash Hackers Wiki:
[
"$@"
] отражает все позиционные параметры так, как они были установлены изначально и переданы в скрипт или функцию. Если вы хотите повторно использовать ваши позиционные параметры для вызова другой программы (например, в скрипте-обертке), то этот выбор для вас, используйте двойные кавычки"$@"
,
Ну, давайте просто скажем: вы почти всегда хотите процитировать"$@"
!