compgen -G
我遇到了一种情况,我正在通过管道输出to的输出,但在添加如下所示的参数xargs basename
之前无法使其工作。xargs -I
这是一个脚本,演示了我正在尝试做的事情,并附有解释性注释。我有两个问题,它们出现在脚本之后。
# create three files for testing:
touch /tmp/my.file.1.2.txt
touch /tmp/1.my.file.2.txt
touch /tmp/1.2.my.file.txt
# create a glob and verify that it works with compgen:
glob=/tmp/*.file*.txt
compgen -G "$glob"
#output:
/tmp/1.2.my.file.txt
/tmp/1.my.file.2.txt
/tmp/my.file.1.2.txt
# try to get the basename of each file using xargs.
# I thought this would work, but it does not.
compgen -G "$glob" | xargs basename
#output:
basename: extra operand ‘/tmp/my.file.1.2.txt’
Try 'basename --help' for more information.
# eventually I discovered that this would work.
# however, I don't understand why this would work
# but the previous attempt would not, since I
# think that this command is just a more
# explicitly-specified version of the previous
# one.
compgen -G "$glob" | xargs -I{} basename {}
#output:
1.2.my.file.txt
1.my.file.2.txt
my.file.1.2.txt
xargs
其他命令无需参数即可使用-I
。例如,compgen -G "$glob" | xargs ls -al
工作得很好。
basename
问题1:这个脚本中需要参数的内容是什么-I
?
问题 2:在观察到这个结果之前,我会认为 和xargs basename
是xargs -I{} basename {}
彼此的同义词,但显然它们不是。有什么不同?
我怀疑这是否重要,但以防万一:这种情况发生在 Ubuntu 20.04.4 (5.13.0-35-generic) 上运行的 bash 5.0.17(1)-release 上。
我知道还有其他方法可以生成此文件列表,但我很担心,因为我显然不理解这里的一些基本内容,我需要理解这些内容以避免将来出现错误。
答案1
POSIXbasename
一次仅处理一个名称,可以选择删除后缀。xargs basename
尝试basename
一次运行尽可能多的参数,但失败了;xargs -I{} basename {}
导致每个名称xargs
运行一次来处理。basename
比较输出
printf "foo\nbar\nbaz" | xargs echo basename
和
printf "foo\nbar\nbaz" | xargs -I{} echo basename {}
GNUbasename
支持多个选项来允许多个名称;如果不需要指定后缀:
xargs basename -a
如果你这样做了,
xargs basename -s .suffix