【问题标题】:xargs -I {} ls {}* : cannot access no such file or directoryxargs -I {} ls {}* : 无法访问没有这样的文件或目录
【发布时间】:2020-10-06 22:58:31
【问题描述】:

假设我有一个名为test 的工作目录。在这个文件夹中,我有许多子目录:

$ ls */*
00/0a:
file1.txt

01/0b:
file2.txt

02/0c:
file3.txt

现在我想得到相同的结果,但使用这样的 xargs:

$ ls | xargs -I {} ls {}/*
ls: cannot access 00/*: No such file or directory
ls: cannot access 01/*: No such file or directory
ls: cannot access 02/*: No such file or directory

我不明白为什么使用* 不起作用。 有替代品吗?

【问题讨论】:

标签: bash xargs


【解决方案1】:

为什么它不能使用 *

文件名扩展(即用文件参数列表替换*)由shell 完成,因此要将* 扩展为文件名列表,您必须调用shell。因为xargs 在传递参数时不会调用shell,所以没有任何东西可以将* 扩展为文件列表。因为您没有按字面意思命名为* 的文件,所以ls 退出并出现错误。

还有其他选择吗?

你可以:

# DO NOT PARSE LS.
# Do not use xargs without -d when you do not want ' " \ to be handled specially.
# Do not pass arguments right into subshell, it's as unsafe as eval.
ls | xargs -I{} sh -c 'ls {}/*'
# Not really better as it parses ls.
ls | xargs -d'\n' -n1 sh -c 'ls "$1"/*' _

但不要解析 ls - 而是根据文件名扩展生成列表:

# acceptable - newline separated list, properly passing arguments
printf "%s\n" * | xargs -d'\n' -n1 sh -c 'ls "$1"/*' _
# great - zero separated list, properly passing arguments
# ie. use this
printf "%s\0" * | xargs -0 -n1 sh -c 'ls "$1"/*' _

或者使用具有相似但不同行为的 find 来代替 shell 文件名扩展:

find . -maxdepth 1 -mindepth 1 | xargs -d'\n' ...
find . -maxdepth 1 -mindepth 1 -print0 | xargs -0 ...

您还可以将 ls 调用从文件名扩展中分离出来,并分两次执行 - 首先对文件运行文件名扩展,然后将结果列表传递给 ls

printf "%s\0" * | xargs -0 -n1 sh -c 'printf "%s\0" "$1"/*' _ | xargs -0 ls

您可能可以正确引用参数列表并使用/* 为它们添加后缀,然后重新evalulate 列表以在所有参数上触发* 上的文件名扩展,这将只调用一个ls和一个子shell,所以是最快的(虽然 eval 看起来很危险,我担心它,它似乎工作正常):

printf "%q/*\0" * | xargs -0 sh -c 'eval ls "$@"' _

【讨论】:

    猜你喜欢
    • 2016-02-26
    • 2019-03-31
    • 2013-09-07
    • 1970-01-01
    • 2017-02-10
    • 1970-01-01
    • 1970-01-01
    • 2020-08-18
    • 1970-01-01
    相关资源
    最近更新 更多