【发布时间】:2013-01-22 11:40:09
【问题描述】:
我一直在尝试将ls 的结果通过管道传输到我正在编写的 C 程序的命令行中(在 Unix 中)。我希望能够拥有文件的索引,所以我打算使用 argv。这就是我认为它应该工作的方式:
./foo &(ls ~/path)
它不起作用 - 将ls 的输出作为参数传递给命令的正确方法是什么?
【问题讨论】:
我一直在尝试将ls 的结果通过管道传输到我正在编写的 C 程序的命令行中(在 Unix 中)。我希望能够拥有文件的索引,所以我打算使用 argv。这就是我认为它应该工作的方式:
./foo &(ls ~/path)
它不起作用 - 将ls 的输出作为参数传递给命令的正确方法是什么?
【问题讨论】:
你的语法有点...
./foo $(ls ~/path)
请注意,这会阻塞包含某些字符的文件。改用数组来解决这个问题。
pushd ~/path
files=(*)
popd
./foo "${files[@]}"
【讨论】:
您指定的符号做了两件事:
./foo &
在后台运行程序foo(除了它的命令名之外没有任何参数)。那么:
(ls ~/path)
在子 shell 中运行 ls 命令(在这种情况下,它与在主 shell 中运行相同)。问题是您打算(或需要)使用$ 代替&。
./foo $(ls ~/path)
这将运行命令ls ~/path 并捕获输出,将其拆分为单词(使用$IFS 变量中列出的分隔符)。然后根据需要将每个单词作为参数提供给命令./foo。
然后我们可以讨论像这样使用ls 的输出是否明智,但除非你的文件名包含空格(制表符、换行符等),否则你会没事的。
【讨论】:
您知道 Unix 工具如何接受 glob 模式,因此您可以使用 cat *.txt 或 rm ~/Pictures/Vacation*.jpg,而无需管道/扩展 ls?
这是你的 shell 为你的程序免费提供的一种能力!
只需使用./foo ~/path/*,argv[1] 将包含/home/you/path/fileone,argv[2] 将包含/home/you/path/filetwo,依此类推。
这些文件名可以是相对的或绝对的,但始终可以直接传递给open/fopen/execve 或您要使用的任何函数。
按照您的描述使用 ls 只会给您文件名的最后一部分,没有目录,因此您将不知道文件在哪里对它们做任何事情(尽管如果这是您想要的,只需使用 @ 987654333@.
【讨论】: