Ada*_*ura 9 command-line bash find arguments
首先切断琐碎但不适用的答案:我既不能使用find+xargs技巧也不能使用它的变体(如findwith -exec),因为我每次调用都需要使用很少的这样的表达式。我会在最后回到这一点。
现在有一个更好的例子,让我们考虑:
$ find -L some/dir -name \*.abc | sort
some/dir/1.abc
some/dir/2.abc
some/dir/a space.abc
Run Code Online (Sandbox Code Playgroud)
我如何将这些作为参数传递给program?
$ ./program $(find -L some/dir -name \*.abc | sort)
Run Code Online (Sandbox Code Playgroud)
失败,因为program得到以下参数:
[0]: ./program
[1]: some/dir/1.abc
[2]: some/dir/2.abc
[3]: some/dir/a
[4]: space.abc
Run Code Online (Sandbox Code Playgroud)
可以看出,带有空间的路径被拆分并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
Run Code Online (Sandbox Code Playgroud)
由于引号可防止分词,因此所有文件都作为单个参数传递。
一个有前途的方法:
$ ./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"
Run Code Online (Sandbox Code Playgroud)
引号在那里,当然。但它们不再被解释。它们只是字符串的一部分。所以他们不仅没有阻止分词,而且还发生了争论!
然后我尝试玩弄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
Run Code Online (Sandbox Code Playgroud)
所以它仍然在空间上分裂并且不会在null.
我试图将IFS分配放在$(…)(如上所示)和之前./program。我还尝试了其他语法,如\0, \x0,\x00都用'和引用,"以及用和不用$. 这些似乎都没有任何区别......
在这里,我没有想法。我尝试了更多的东西,但似乎都遇到了与所列相同的问题。
我还能做什么?它完全可行吗?
当然,我可以让program接受模式并自行搜索。但是在将其修复为特定语法时需要进行大量双重工作。(grep例如,提供文件怎么样?)。
我也可以让program接受一个带有路径列表的文件。然后我可以轻松地将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
Run Code Online (Sandbox Code Playgroud)
所以xargs从一个搜索中进行搜索仍然让我知道如何处理另一个......
ste*_*ver 14
使用数组。
如果您不需要处理文件名中出现换行符的可能性,那么您可以逃脱
mapfile -t ABC_FILES < <(find -L some/dir -name \*.abc | sort)
mapfile -t XYZ_FILES < <(find -L other/dir -name \*.xyz | sort)
Run Code Online (Sandbox Code Playgroud)
然后
./program --abc-files "${ABC_FILES[@]}" --xyz-files "${XYZ_FILES[@]}"
Run Code Online (Sandbox Code Playgroud)
如果您确实需要处理文件名中的换行符,并且 bash >= 4.4,则可以在数组构造期间使用-print0和-d ''以空终止名称:
mapfile -td '' ABC_FILES < <(find -L some/dir -name \*.abc -print0 | sort -z)
Run Code Online (Sandbox Code Playgroud)
(对于 ,类似XYZ_FILES)。如果您没有较新的 bash,那么您可以使用以空字符结尾的读取循环将文件名附加到数组中,例如
ABC_FILES=()
while IFS= read -rd '' f; do ABC_FILES+=( "$f" ); done < <(find -L some/dir -name \*.abc -print0 | sort -z)
Run Code Online (Sandbox Code Playgroud)