使用“less”在屏幕上保留小文件的文本

使用“less”在屏幕上保留小文件的文本

我很确定很久以前就在某些同事的系统上看到过这种对 less 命令的定制,以模仿“more”。我想要的是:

  • 如果文件很短(不到一屏长),它的行为应该像 cat:它显示文件的内容并退出。

  • 如果文件长于一个屏幕,它应该像往常一样运行,等待用户输入并在退出时清除屏幕并将先前的命令保留在屏幕上。

我尝试过使用较少的 -FX 进行实验,但对于大文件来说,它会在屏幕上留下大量内容。

答案1

如果我理解正确,您希望保留大文件的备用屏幕切换行为,并仅针对适合单个屏幕且不需要滚动的小文件打开 -X 开关。

现在这是 530 版本中的默认行为lessNEWS从文件中引用源代码:

较小版本 487 和 530 之间的主要变化

  • -F如果使用和 文件适合一个屏幕,则不要输出终端初始化序列。

不幸的是,截至 2019 年,一些发行版(例如 Debian 10)仍然使用旧版本的less,因此如果您不想从来源,唯一的解决方案是使用包装器。

这是此类包装器的示例。其已知的局限性是A):n:p(下一个/上一个文件)命令不起作用less——命令行中的所有文件都连接在一个流中,并且b)它无法处理输入中的空字节,除非/usr/bin/awk实际上是gawk(GNU Awk)或 Thomas Dickey 的莫克

#! /usr/bin/awk -f
BEGIN { "tput lines" | getline max; max -= 2 }
{ l[NR]=$0 }
NR>=max {
        for(i = 1; i <= NR; i++) print l[i] | "less";
        while(getline > 0) print | "less";
}
END { if (NR < max) for(i = 1; i <= NR; i++) print l[i] | "less -FX" }

答案2

没有简单的方法可以解决这个问题。

您要么less使用备用屏幕来保持原始屏幕的原始状态,要么不使用(使用-X)。

您不能真正期望less将屏幕恢复原样,并在读取整页后开始使用备用屏幕。

我们需要以某种方式等待至少一页或 eof 被读取,然后才能less以正确的模式启动并发送数据。就像是:

page_stdin() {
  awk -v l="${LINES:=$(tput lines)}" '
    cmd {print | cmd; next}
    {lines = lines $0 ORS}
    NR == l {cmd = "less"; printf "%s", lines | cmd}
    END {if (!cmd) printf "%s", lines | "less -FX"}'
}
mypager() {
  if [ "$#" -eq 0 ]; then
    page_stdin
  else
    for file do page_stdin < "$file"; done
  fi
}

(使用 GNU awk,您可以替换ORS为,RT如果一开始就不存在尾随换行符,则不添加)。

但这意味着您不会开始看到管道命令的输出,cmd | mypager直到有一整页的内容或它完成输出为止。 (例如尝试seq 200 | pv -qL40 | mypager与 进行比较seq 200 | pv -qL40 | less)。

请注意,它假设您不使用类似的东西LESS=-s,并且会被大于屏幕的线条所欺骗,除非您有LESS=-S

答案3

将其粘贴到您的终端上(或将其放在 bashrc 上):

less_cat(){
     [ "$(wc -l <"$1")" -ge "$LINES" ] && less "$1" || less -FX "$1"
}

现在您应该能够执行:

less_cat /etc/fstab
less_cat /var/log/messages 

它会完全按照您的意愿行事。

笔记:该解决方案兼容BASH/ZSH(见评论)

祝你好运!

相关内容