xargs -I {} ls {}* :无法访问没有这样的文件或目录
xargs -I {} ls {}* : cannot access no such file or directory
假设我有一个名为 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
我不明白为什么它不能使用 *
。
有替代方案吗?
why it doesn't work using the *
文件名扩展(即用文件参数列表替换 *
)由 shell 完成,因此要将 *
扩展到您拥有的文件名列表调用 shell。因为 xargs
在传递参数时不调用 shell,所以没有任何东西可以将 *
扩展到文件列表。因为您没有字面上名为 *
的文件,所以 ls
退出并出错。
Is there an alternative ?
你可以:
# 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 ""/*' _
但不要解析 ls - 而是根据文件名扩展生成列表:
# acceptable - newline separated list, properly passing arguments
printf "%s\n" * | xargs -d'\n' -n1 sh -c 'ls ""/*' _
# great - zero separated list, properly passing arguments
# ie. use this
printf "%s[=11=]" * | xargs -0 -n1 sh -c 'ls ""/*' _
或者不使用 shell 文件名扩展,而是使用具有类似但不同行为的查找:
find . -maxdepth 1 -mindepth 1 | xargs -d'\n' ...
find . -maxdepth 1 -mindepth 1 -print0 | xargs -0 ...
您也可以将 ls
调用从文件名扩展中分离出来,分两次进行 - 首先 运行 文件名扩展,然后结果列表传递给 ls
:
printf "%s[=13=]" * | xargs -0 -n1 sh -c 'printf "%s[=13=]" ""/*' _ | xargs -0 ls
可能你可以正确引用参数列表并用 /*
后缀,然后重新 eval
ulate 列表以在所有参数上触发 *
上的文件名扩展,这将只调用一个 ls
和一个 subshell 所以是最快的(虽然 eval 看起来很危险而且我担心它,但它似乎工作正常):
printf "%q/*[=14=]" * | xargs -0 sh -c 'eval ls "$@"' _
假设我有一个名为 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
我不明白为什么它不能使用 *
。
有替代方案吗?
why it doesn't work using the *
文件名扩展(即用文件参数列表替换 *
)由 shell 完成,因此要将 *
扩展到您拥有的文件名列表调用 shell。因为 xargs
在传递参数时不调用 shell,所以没有任何东西可以将 *
扩展到文件列表。因为您没有字面上名为 *
的文件,所以 ls
退出并出错。
Is there an alternative ?
你可以:
# 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 ""/*' _
但不要解析 ls - 而是根据文件名扩展生成列表:
# acceptable - newline separated list, properly passing arguments
printf "%s\n" * | xargs -d'\n' -n1 sh -c 'ls ""/*' _
# great - zero separated list, properly passing arguments
# ie. use this
printf "%s[=11=]" * | xargs -0 -n1 sh -c 'ls ""/*' _
或者不使用 shell 文件名扩展,而是使用具有类似但不同行为的查找:
find . -maxdepth 1 -mindepth 1 | xargs -d'\n' ...
find . -maxdepth 1 -mindepth 1 -print0 | xargs -0 ...
您也可以将 ls
调用从文件名扩展中分离出来,分两次进行 - 首先 运行 文件名扩展,然后结果列表传递给 ls
:
printf "%s[=13=]" * | xargs -0 -n1 sh -c 'printf "%s[=13=]" ""/*' _ | xargs -0 ls
可能你可以正确引用参数列表并用 /*
后缀,然后重新 eval
ulate 列表以在所有参数上触发 *
上的文件名扩展,这将只调用一个 ls
和一个 subshell 所以是最快的(虽然 eval 看起来很危险而且我担心它,但它似乎工作正常):
printf "%q/*[=14=]" * | xargs -0 sh -c 'eval ls "$@"' _