Это краткое представление файлов в текущем каталоге. bash
расширит его до того же, что и вывод ls
.
Пример - file{a,b}.txt
расширяется до filea.txt fileb.txt
в bash
. Таким образом, что-то вроде cp file{a,b}.txt
расширяется до cp filea.txt fileb.txt
, что скопирует filea.txt в fileb.txt.
Это оболочка, которая устанавливает конвейер. less
в этом не участвует.
Когда вы выполняете ls | less
, оболочка запускает ls
и less
одновременно после создания stdout процесса, который в конечном итоге выполнит ls
запись конца канала и stdin того, который будет выполняться. выполнить less
конец чтения той же трубы.
ls
определяет, что его стандартный вывод не является tty-устройством, и соответствующим образом изменяет свое поведение. less
ничего не может с этим поделать.
Оболочка могла бы использовать пару псевдотерминалов -вместо канала для соединения двух процессов, но это было бы плохой идеей, поскольку псевдотерминалы -не были разработаны. для этого. Во-первых, разрыв связи будет проблематичным. less
, вероятно, был бы сбит с толку, если бы его стандартный ввод был мастером терминала псевдо -.
Другим подходом может быть получение третьего процесса, который считывает выходные данные ls
через пару псевдотерминалов -и передает их less
через конвейер, как @JdeBP ptyrun
или ptybandage
, или expect
unbuffer
, или с помощью zsh
zpty
встроенной:
zmodload zsh/zpty
ttypager() { (zpty c "stty raw -echo; ${(q)@}"; zpty -r c) | less -RFX; }
ttypager ls
ls
будет работать в новом сеансе в новом терминале, поэтому не будет получать SIGINT при нажатии ^C или SIGPIPE при выходе из less
до завершения записи. Однако, поскольку процесс, удерживающий главную сторону (подоболочкой здесь ), все еще будет в этих случаях ls
получать SIGHUP и, тем не менее, умирать.
zpty
здесь запускает команду, как если бы она использовала eval
, так что псевдонимы будут расширены. Фактически,они будут расширены, даже если вы вызовете ttypager \ls
, так как ttypager
все равно получит ls
в качестве аргумента и позже выполнит расширение псевдонима.
Также обратите внимание, что и stdout, и stderr отправляются на этот псевдо-терминал -и, в конечном итоге, в канал.
Это все еще немного грязный хак. Здесь самым простым было бы указать ls
вести себя так, как если бы он был подключен к терминалу.
Вы можете использовать вспомогательную функцию, например:
paged_ls() { ls -C --color=always "$@" | less -RFX; }
Где -C
принудительно выводит вывод в столбце (, что некоторые реализации, включая GNU ls
, делают по умолчанию, когда вывод идет на терминал )и --color=always
принудительно выводят вывод в цвете независимо от того, является ли вывод идет к терминалу или нет.
Общий способ сделать это — использовать такие инструменты, как инструмент Бернштейна ptybandage
:
$ ptybandage ls > wibble ; less wibble.
Или, лучше в данном случае, Бернштейнаptyrun
:
$ ptyrun ls | less
ptyrun
. djbwares . ptybandage
. djbwares . ptyrun
. Направляющая ноша . Программное обеспечение. ptybandage
. Направляющая ноша . Программное обеспечение.