Bash:获取修改后的类似 ls 的输出(每行多个条目)

Bash: Get modified `ls`-like output (multiple entries per line)

当您在命令行中调用 ls 时没有附加选项,您每行会得到多个条目。

人为的例子:

$ ls mydir/*.tar.gz
mydir/foo.tar.gz        mydir/bar.tar.gz        mydir/baz.tar.gz

但是如果你想以某种方式修改输出,你每行得到一个条目:

$ ls mydir/*.tar.gz | sed "s/\.tar\.gz//g"
mydir/foo
mydir/bar
mydir/baz

有很多条目,这变得很麻烦 -- 我想要多个对齐的列。

我试图按照 find mydir -name "*.tar.gz" -printf ...... -exec ... 或什至(yuk!)for file in $(find ...) 的思路想出一些东西,但我能想出的任何东西都很臭真的很不优雅(想想计数器变量,取模并只是猜测终端宽度......)。

有没有一些优雅的方法可以像香草 ls 那样在多列输出中获取几个文件名,然后修改它们(例如 sedbasename等等)?

ls -C 强制多列输出,即使输出远离控制台也是如此。

(令人惊讶的命名)column 命令将执行您想要的操作。

ls | column -c 80

这将在 80 宽显示器的列中显示输出。您可能需要等待输出,因为它必须先计算出项目的宽度,然后才能格式化任何内容。

它适用于任何命令。

您可以使用 COLUMNS 环境变量找到您的列宽(这可能取决于您的 shell - 输入 set 以查看变量列表并计算出来),或使用 tput cols 命令。

更新免责声明:

  • 这个答案对 OP 不起作用,因为他想先 修改 ls 输出,然后 然后 列它;因此,必须在 separate pass 中应用列,later,这是 通过 column -c <n> 提供的。
  • 此答案仅在您想要使用分栏 ls 输出 原样 时才有效。
    • 除此之外,它还提供了一些可能有趣的背景信息,关于 ls 如何决定如何格式化其输出以及最大。它假定的线宽。

建立在 的基础上,它指出 -C 明确请求来自 ls 的多列输出:

tl;dr

向文件发送内容时模拟ls的多列终端输出或通过管道 使用当前终端的最大值。 line width(单字符显示列数),使用COLUMNS=$(tput cols) ls -C;例如:

COLUMNS=$(tput cols) ls -C | cat  # `| cat` is an example command to show pipe behavior

显然,你也可以独立于当前终端选择固定号码;例如,COLUMNS=120 ls -C ...

如果没有 COLUMNS=... 前缀,将根据最大值进行分栏。 80 的线宽,与终端 window 的实际宽度无关。


注:以下部分为推测。如果我错了请告诉我。

ls,当输出到终端时

  • 默认生成分栏(多列)输出(隐含-C
  • 确定终端的最大值。线宽本身.[1]

相比之下,当ls的标准输出连接到管道或输出文件时,它

  • 默认为逐行输出(隐含-1
  • 当指定 -C 时,它从 COLUMNS environment 变量(不是 shell变量);如果没有这个变量,默认是 80.

bashshell中,$COLUMNS通常是shell中的变量集 interactive shell only,不是 environment 变量 - 换句话说:定义了 $COLUMNS,但未定义 exported.

要让 ls 遵守 $COLUMNS 变量,您必须将其定义为 environment 变量。

最简洁的方法是在调用 ls 之前添加一个 ad-hoc,命令本地环境变量定义(一般模式是:<envVar>=<value> <commmand> ...):

由于tput cols returns当前终端的线宽,我们得到:

COLUMNS=$(tput cols) ls -C ...

tput cols 也适用于脚本,因此这是一种稳健的方法;交互地,看似毫无意义的命令 COLUMNS=$COLUMNS ls -C 也可以工作。

请注意,ls 在输出到 终端时甚至会遵守 COLUMNS 环境变量


[1] 也就是说,它 不需要 环境变量 COLUMNS,但如果已定义,则尊重它。请注意,一个名为 COLUMNS 的(未导出的)shell 变量 - 作为交互式 shells 中的典型情况 - 是 忽略.