将文件内容导入ls

9

我有一个名为"input.txt"的文件,其中包含一行:

/bin

我希望将文件的内容作为ls命令的输入。

我尝试执行:

cat input.txt | ls

但它没有输出/bin目录中的文件列表。
我也尝试过。
ls < input.txt

无济于事。

3
使用 ls \cat in.txt`` 命令会更简单。 - cs95
@Coldspeed 一般来说,这也是错误的。 - chepner
1
@chepner 它在我的Mac上运行良好。这是一个安全问题吗? - cs95
尝试运行以下代码:f=$'foo\tbar'; touch "$f"; echo "$f" > input.txt; ls $(cat input.txt) - chepner
3个回答

12

你正在寻找 xargs转置参数)命令。

xargs ls < input.txt

你说你想让/bin成为ls的“输入”,但那是不正确的;ls不会对其输入执行任何操作。相反,你希望将/bin作为命令行参数传递给ls,就像你键入ls /bin一样。

输入和参数是完全不同的东西;将文本作为输入提供给命令并不等同于将该文本作为参数提供。许多命令(如cat)可以操作它们的输入或参数(或两者兼而有之),这种区别可能会变得模糊 - 但即使在这种情况下,我们也发现了一个重要的区别:它们实际上操作的是通过参数传递的文件名所对应的文件内容

xargs命令是专门设计用来在这两种情况之间进行转换的:它将其输入解释为要传递给某些其他命令的以空格分隔的命令行参数列表。这个其他命令作为xargs的命令行参数被提供,此时为ls

由于 shell 通过<提供了输入重定向,因此这里xargs提供给ls的参数来自input.txt文件。

有其他的方式可以实现同样的效果;例如,只要input.txt中的文件不太多,超过单个命令行无法容纳,你就可以这样做:

ls $(< input.txt)

以上两个命令以及xargs版本都会把input.txt文件中的任何空格视为分隔文件名,因此如果您的文件名包含空格字符,则需要更多工作来正确解释文件。另外,请注意,如果任何文件名包含通配符/“glob”字符,如?*[...],则$(<...)版本将它们扩展为通配符模式,而xargs则不会。


1
非常有帮助!感谢指出输入和命令行参数之间的区别。 - Timothy Samson
ls $(< input.txt)有很多异常情况,甚至不值得一提。 - chepner

3

ls 命令从命令行获取文件名,而不是标准输入流,这一点需要注意,因为 | lsls < file 只能从标准输入中获取文件名。

如果只有一个文件在 input.txt 中,并且文件名没有换行符,那么只需要使用如下命令即可(请注意双引号):

ls "$(cat input.txt)"

或者几乎在所有但纯POSIX shell中:

ls "$(< input.txt)"

如果文件中有很多文件名,您会想要使用xargs,但为了处理名称中的空格,请使用-d "\n" (使用GNU xargs)将每行视为一个文件名。
xargs -d "\n" ls < input.txt

如果你需要处理带有换行符的文件名,你可以在输入时使用NUL字节进行分隔,并使用

xargs -0 ls < input.txt

(即使只有一个文件名,这也适用。)

1

尝试使用xargs

cat file | xargs ls

哦,我得加这句话才能让字符数达到30个;)

1
这种方法的效率比没有使用cat的版本低(在没有使用cat的版本中,xargs直接从输入文件中读取,而不是从与另一个程序连接的FIFO中读取)。 - Charles Duffy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接