为什么我需要在`compgen -G ... | 中使用-I参数xargs 基名`?

为什么我需要在`compgen -G ... | 中使用-I参数xargs 基名`?

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 basenamexargs -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

相关内容