简而言之,我想在命令中使用命令列出的目录find
:
find $(produces_dir_names --options...) -find-options...
问题在于目录名称中存在空格。我认为在生成命令的输出中引用它们(我可以更改)就足够了:
"a" "a b" "a b c"
但 bash 抱怨道:
find: ‘"a"’: No such file or directory
find: ‘"a’: No such file or directory
find: ‘b"’: No such file or directory
find: ‘"a’: No such file or directory
find: ‘b’: No such file or directory
find: ‘c"’: No such file or directory
如您所见, seebash
会在空格上分割命令的输出,即使使用引号也是如此。我尝试摆弄IFS
并将其设置为\n
,但我对它的理解似乎太有限,无法使其正常工作。
我发现的唯一解决方法是在这个 Stack Overflow 问题中:
bash命令替换删除引号,即eval
在它前面放一个,但这看起来有点难看。
我的问题:
有没有一种简单的方法以及在没有 的情况下编写此替换会是什么样子eval
?
报价还有必要吗?
示例(产生相同的输出):
find $(echo '"a" "a b" "a b c"')
答案1
也许分两行
IFS=$'\n' DIRS=( $(produces_dir_names --options...) )
find "${DIRS[@]}" -find-options...
例子:
$ mkdir -p "/tmp/test/a b/foo" "/tmp/test/x y/bar"
$ IFS=$'\n' DIRS=( $(printf "/tmp/test/a b\n/tmp/test/x y\n") )
$ find "${DIRS[@]}" -mindepth 1
/tmp/test/a b/foo
/tmp/test/x y/bar
但总的来说,这不是一个好的风格。例如,如果您的 DIRS 包含换行符,您就会遇到麻烦。更好地修复您的“ Produces_dir_names”以打印空字节终止的字符串。关于我的例子,这将是这样的:
$ printf "/tmp/test/a b\0/tmp/test/x y\0" | xargs -0 -I '{}' find '{}' -mindepth 1
/tmp/test/a b/foo
/tmp/test/x y/bar
如果您无法修复“products_dir_names”,则关于我的最后一条评论,最通用的解决方案将如下所示:
produces_dir_names --options... | tr '\n' '\0' | xargs -0 -I '{}' find '{}' -find-options...
除非您修复“ Produces_dir_names”以避免“换行符”,否则“换行符”仍然存在问题tr
。
答案2
鲁迪迈尔的回答很好——具体来说,关于修改produces_dir_names
以打印空终止字符串的部分——但从他的回答中可能并不明显看出它find
为每个目录执行一次。如果这足够好,那就好了。但是,当然,可以使用find
多个起点进行调用;例如,
寻找 目录1目录2目录3 -查找选项...
从问题看来这就是你想要的。这可以按如下方式完成:
printf "a\0a b\0a b c" | printf "a\0a b\0a b c" | xargs -0 sh -c '查找“$@”-查找选项...' 什
这会导致xargs
调用sh -c
一次,并将所有目录名称附加到命令中。然后,shell 将展开"$@"
这些目录名称的列表。
PS 如果produces_dir_names
列出太多目录名称而无法放在一个命令行上,则将xargs
被迫生成一些命令。用于xargs --verbose
查看xargs
正在生成哪些命令。
答案3
只是为了揭开您收到的错误消息的神秘面纱:
find: ‘"a"’: No such file or directory find: ‘"a’: No such file or directory find: ‘b"’: No such file or directory find: ‘"a’: No such file or directory find: ‘b’: No such file or directory find: ‘c"’: No such file or directory
答案是Bash 引号删除不会删除以下引号结果来自命令替换。
从LESS='+/^ *Quote Removal' man bash
Quote Removal After the preceding expansions, all unquoted occurrences of the charac- ters \, ', and " that did not result from one of the above expansions are removed.
引用的“前述扩展”包括:
EXPANSION Brace Expansion Tilde Expansion Parameter Expansion Command Substitution Arithmetic Expansion Process Substitution Word Splitting Pathname Expansion Quote Removal