我正在使用以下命令:
\cp -uf /home/ftpuser1/public_html/ftparea/*.jpg /home/ftpuser2/public_html/ftparea/
我收到了错误:
-bash: /bin/cp: Argument list too long
我也尝试过:
ls /home/ftpuser1/public_html/ftparea/*.jpg | xargs -I {} cp -uf {} /home/ftpuser2/public_html/ftparea/
仍然出现 -bash: /bin/ls: 参数列表太长
有任何想法吗?
答案1
*.jpg 扩展为一个比 shell 可以处理的长度更长的列表。请尝试以下方法
find /home/ftpuser/public_html/ftparea/ -name "*.jpg" -exec cp -uf "{}" /your/destination \;
答案2
系统命令的参数列表长度有一个最大限制 —— 此限制是基于MAX_ARG_PAGES
内核编译时的值的特定于发行版的,并且如果不重新编译内核就无法更改。
由于 shell 处理通配符的方式,当您使用相同的参数(“*.jpg”)时,这将影响大多数系统命令。由于通配符首先由 shell 处理,然后发送给命令,因此命令:
cp -uf *.jpg /targetdir/
与 shell 中编写的代码基本相同:
cp -uf 1.jpg 2.jpg ... n-1.jpg n.jpg /targetdir/
如果你要处理大量的 jpeg,那么很快就会变得难以管理。根据你的命名约定和实际需要处理的文件数量,你可以运行cp一次对目录的不同子集执行命令:
cp -uf /sourcedir/[a-m]*.jpg /targetdir/
cp -uf /sourcedir/[n-z]*.jpg /targetdir/
这可能会起作用,但具体效果取决于您能多好地将文件列表分解为方便的可全局块。
Globbable。我喜欢这个词。
一些命令,例如寻找和参数,可以处理大型文件列表,而不需要制作大小合适的参数列表。
find /sourcedir/ -name '*.jpg' -exec cp -uf {} /targetdir/ \;
-exec 参数将对找到的每个文件运行一次命令行的其余部分寻找,用找到的每个文件名替换 {}。由于cp命令一次只能对一个文件运行,参数列表限制不是问题。
由于必须单独处理每个文件,因此这可能会很慢。使用参数可以提供更有效的解决方案:
find /sourcedir/ -name '*.jpg' -print0 | xargs -0 cp -uf -t /destdir/
参数可以获取提供的完整文件列表寻找,并将其分解为可管理大小的参数列表并运行cp在每个子列表上。
当然,也可以重新编译内核,为 设定一个更大的值MAX_ARG_PAGES
。但是重新编译内核的工作量比我愿意在这个答案中解释的要大。
答案3
发生这种情况是因为您的通配符表达式(*.jpg
)在扩展时超出了命令行参数的长度限制(可能是因为您下有很多 .jpg 文件/home/ftpuser/public_html/ftparea
)。
有几种方法可以绕过这个限制,比如使用find
或xargs
。看看本文了解有关如何执行此操作的更多详细信息。
答案4
程序可以指定的参数数量是有上限的,bash 会将 *.jpg 扩展为许多 cp 参数。您可以使用 find、xargs 或 rsync 等来解决此问题。
看看这里关于 xargs 和 find