我有如下一行:
find /foo/bar -name '*.mp4' -print0 | xargs -i {} -0 mv -t /some/path {}
但我收到以下错误:
xargs: argument line too long
我很困惑。难道使用 Shouldxargs
正好可以帮助解决这个问题吗?
笔记:我知道我可以-exec
在技术上使用 find ,但我想了解为什么上述失败,因为我的理解是xargs
应该知道如何将输入分割成可管理的大小以适应其运行的参数。这不是真的吗?
这一切都与 zsh 相关。
答案1
一方面,该-i
开关已被弃用:
-i[replace-str]
This option is a synonym for -Ireplace-str if replace-str is specified.
If the replace-str argument is missing, the effect is the same as -I{}.
This option is deprecated; use -I instead.
所以当我将你的命令更改为这个时,它起作用了:
$ find /foo/bar -name '*.mp4' -print0 | xargs -I{} -0 mv -t /some/path {}
例子
$ find . -print0 | xargs -I{} -0 echo {}
.
./.sshmenu
./The GIT version control system.html
./.vim_SO
./.vim_SO/README.txt
./.vim_SO/.git
./.vim_SO/.git/objects
./.vim_SO/.git/objects/pack
./.vim_SO/.git/objects/pack/pack-42dbf7fe4a9b431a51da817ebf58cf69f5b7117b.idx
./.vim_SO/.git/objects/pack/pack-42dbf7fe4a9b431a51da817ebf58cf69f5b7117b.pack
./.vim_SO/.git/objects/info
./.vim_SO/.git/refs
./.vim_SO/.git/refs/tags
...
用于-I{}
自从运行此命令构造后,不应使用此方法:
$ find -print0 ... | xargs -I{} -0 ...
隐式地将这些开关打开为xargs
、-x
和-L 1
。配置以便它调用您希望它以单一方式运行文件的命令-L 1
。xargs
因此,这违背了此处使用的目的,xargs
因为如果您给它 1000 个文件,它将运行该mv
命令 1000 次。
那么我应该使用哪种方法呢?
您可以使用 xargs 来完成此操作,如下所示:
$ find /foot/bar/ -name '*.mp4' -print0 | xargs -0 mv -t /some/path
或者只是找到完成这一切:
$ find /foot/bar/ -name '*.mp4' -exec mv -t /some/path {} +
答案2
该选项-i
采用可选参数。由于您在后面放置了一个空格-i
,因此该选项没有参数-i
,因此后续的选项-0
不是xargs
6 个操作数中的第二个,而是 6 个操作数中的第二个{} -0 mv -t /some/path {}
。
仅使用选项 时-i
,xargs 需要换行符分隔的文件名列表。由于输入中可能没有换行符,因此 xargs 收到了看起来很大的文件名(带有嵌入的空字节,但 xargs 没有检查)。包含整个输出的单个字符串find
比最大命令行长度长,因此出现错误“命令行太长”。
您的命令将使用-i{}
而不是-i {}
.或者,您可以使用-I {}
:-I
与 类似-i
,但采用强制参数,因此传递给 的下一个参数xargs
将用作选项的参数-I
。然后后面的参数 is-0
被解释为选项,依此类推。
但是,您-I {}
根本不应该使用。使用-I
具有三个作用:
-I
关闭报价处理,这-0
已经完成了。-I
更改要替换的字符串,但{}
为默认值。-I
导致为每个输入记录单独执行该命令,这在这里是无用的,因为您的命令 (mv -t
) 专门用于处理每次调用的多个文件。
要么放弃-I
,要么-i
完全
find /foo/bar -name '*.mp4' -print0 | xargs -0 mv -t /some/path {}
或删除 xargs 并使用-exec
:
find /foo/bar -name '*.mp4' -exec mv -t /some/path {} +
答案3
尝试使用 bash for 循环:
for FILE in *.mp4 ; do rm $FILE ; done
或者如果您想看看发生了什么:
for FILE in *.mp4 ; do echo Removing $FILE ; rm $FILE ; done
答案4
如果您在使用时看到此内容鱼壳。
这与鱼如何扩展替换串有关{}
如果您使用的是 Fish,则需要转义替换字符串\{\}
| xargs -I \{\} echo \{\}
或使用不同的替换字符串
| xargs -I ! echo !