首先要截断一些琐碎但不适用的答案:我既不能使用find
+ xargs
技巧,也不能使用其变体(如find
with -exec
),因为每次调用我需要使用很少的此类表达式。最后,我会回到这一点。
现在来看一个更好的例子,让我们考虑:
$ find -L some/dir -name \*.abc | sort
some/dir/1.abc
some/dir/2.abc
some/dir/a space.abc
我如何将这些作为参数传递给program
?
只是做不成功
$ ./program $(find -L some/dir -name \*.abc | sort)
失败,因为program
获取以下参数:
[0]: ./program
[1]: some/dir/1.abc
[2]: some/dir/2.abc
[3]: some/dir/a
[4]: space.abc
可以看出,带有空间的路径被分割,并program
认为它是两个不同的参数。
报价直到生效
似乎像我这样的新手用户,遇到此类问题时,往往会随机添加引号,直到最终起作用为止-仅在这里似乎没有帮助…
"$(…)"
$ ./program "$(find -L some/dir -name \*.abc | sort)"
[0]: ./program
[1]: some/dir/1.abc
some/dir/2.abc
some/dir/a space.abc
因为引号可以防止单词拆分,所以所有文件都作为单个参数传递。
引用单个路径
一种有前途的方法:
$ ./program $(find -L some/dir -name \*.abc -printf '"%p"\n' | sort)
[1]: "some/dir/1.abc"
[2]: "some/dir/2.abc"
[3]: "some/dir/a
[4]: space.abc"
报价在那里。但是它们不再被解释。它们只是字符串的一部分。因此,它们不仅不会阻止单词分裂,而且还会引起争论!
更改IFS
然后我试着和玩IFS
。我宁愿find
用-print0
和sort
用-z
反正-所以,他们会对“连接路径”自己没有问题。那么,为什么不强加字符拆分功能null
呢?
$ ./program $(IFS=$'\0' find -L some/dir -name \*.abc -print0 | sort -z)
[0]: ./program
[1]: some/dir/1.abcsome/dir/2.abcsome/dir/a
[2]: space.abc
因此它仍然会在空间上分裂,而不会在上分裂null
。
我试图将IFS
作业放置在$(…)
(如上所示)和之前./program
。我也尝试了其他语法,例如\0
和\x0
,\x00
都用'
和"
以及用和不用引用$
。这些似乎都没有任何作用……
在这里,我没主意了。我尝试了几件事,但似乎都遇到了与所列相同的问题。
我还能做什么?完全可行吗?
当然,我可以program
接受模式并进行搜索。但是在将其固定为特定语法时,需要做很多双重工作。(grep
例如,提供文件怎么样?)。
另外,我可以使program
accept带有路径列表的文件。然后,我可以轻松地将find
表达式转储到某些临时文件中,并仅提供该文件的路径。可以沿直接路径进行支持,因此,如果用户只有一条简单路径,则可以不使用中间文件就可以提供该路径。但这似乎不太好-需要创建额外的文件并妥善保管,更不用说需要额外的实现了。(但是,从积极的一面来说,对于文件数量作为参数开始引起命令行长度问题的情况,这可能是一种拯救方法。)
最后,让我再次提醒您,就我而言,find
+ xargs
(和类似方式)技巧无效。为了简化描述,我仅显示一个参数。但是我的真实情况更像是这样:
$ ABC_FILES=$(find -L some/dir -name \*.abc | sort)
$ XYZ_FILES=$(find -L other/dir -name \*.xyz | sort)
$ ./program --abc-files $ABC_FILES --xyz-files $XYZ_FILES
因此,xargs
从一个搜索中进行一次搜索仍然使我剩下如何处理另一个搜索…
mapfile
(或它的同义词readarray
)。但这确实有效!