xargs单命令与复杂命令的差异及sh -c参数丢失问题解析
问题原因
你碰到的问题本质是sh -c的参数处理逻辑和普通命令不同:
sh -c后面紧跟的字符串是要执行的命令脚本,这个脚本会被shell当作自身的$0(即当前shell进程的名称标识)。- 脚本之后的所有参数,才会依次对应
$1、$2、$3……这些位置变量。
拿你的例子来说,xargs把the quick brown fox.h这一组参数传给sh时,实际的调用结构是:
sh -c 'echo "$# -- $*"' the quick brown fox.h
这里'echo "$# -- $*"'是命令脚本,the被分配给了$0,剩下的quick、brown、fox.h对应$1到$3。所以$#统计的是$1到$3的数量(3个),$*输出的是这三个参数——这就是第一个参数the看似被“吃掉”的原因。
解决方法
要让xargs传递的所有参数都进入$1及以后的位置,只需要在sh -c的命令脚本后面加一个占位符(比如_,任意字符串都可以),让它去占用$0的位置:
基础修正版
ls *.h | xargs -L 1 sh -c 'echo "$# -- $*"' _
此时调用结构变成:
sh -c 'echo "$# -- $*"' _ the quick brown fox.h
_作为$0,the、quick、brown、fox.h分别对应$1到$4,$#会显示4,$*输出完整的文件名。
更严谨的版本
如果文件名包含特殊字符或空格,推荐用$@替代$*($@会保留每个参数的独立性,避免空格拆分问题):
ls *.h | xargs -L 1 sh -c 'echo "$# -- $@"' _
内容的提问来源于stack exchange,提问作者thilo
相关产品推荐
相关产品推荐

