【问题标题】:bash: ./script.sh: Argument list too longbash: ./script.sh: 参数列表太长
【发布时间】:2015-04-30 09:15:44
【问题描述】:

我有下面的脚本,我从带有 ./checkres.sh * 甚至 *.jpg 的图像目录中运行它,但它仅适用于少量文件,少于 100 个左右。还有更多,它会因错误“参数列表太长”而停止,我有 100,000 张图像要处理。

我已经在网上搜索了几个小时,尝试了几十种不同的更改,使用 while 代替 for 循环以及对变量的各种其他更改,但似乎没有任何效果。

任何人都可以帮助解决这个谜,因为我是 bash 脚本的新手并且已经没有想法了。

#!/bin/bash
for img in "$@"
do

export height=`identify -format %h "$img"`
export width=`identify -format %w "$img"`
let ratio=$width/$height

echo Image "$img" = [ $width x $height ] = $ratio

if [ $ratio == 0 ]
then
    echo Portrait 0
    convert "$img" -geometry 600x800 -format jpeg -quality 80 "$img"
else
    echo Landscape 1
    convert "$img" -geometry 800x600 -format jpeg -quality 80 "$img"
fi

【问题讨论】:

  • 这里有一些错误。您可以在 shellcheck.net 中查看基本的
  • 使用目录 nene 作为参数不是更好吗?然后你可以在其中放置 TB 的图像,你的脚本不会出错。
  • 顺便说一句——不要对定义命令的脚本使用.sh 扩展。想想如果你用 Python 重写它会发生什么——你是想让所有调用/调用它的东西都改变为运行./checkres.py,还是有一个以.sh 命名的 Python 脚本?就叫它checkres,就像你运行ls,而不是ls.elf
  • 我也会考虑if (( ratio == 0 ));更简单,更易读。如果您想使用 [ ] 进行该测试,则需要对其进行一些调整以使其更加健壮:[ "$ratio" -eq 0 ] 会更好地处理极端情况。
  • @tgo,我还没有完整阅读那篇文章,但它的示例 3a 也有问题。如果没有带有任意名称的-r,就不能安全地使用read(因为这将解释反斜杠转义序列而不是将它们视为文字)——或者,就此而言,不清除IFS并使用NUL分隔的流(处理真正奇怪的情况,例如名称中带有换行符的文件名)。缺乏严谨性令人不安。

标签: linux bash shell


【解决方案1】:

您不需要更改脚本的任何内容;只需改变你调用它的方式:

find . -maxdepth 1 -name '*.jpg' -exec ./checkres.sh '{}' +

这将在每次调用时只放置尽可能多的文件名,并根据需要多次运行脚本。


事实上 -- 除非您更改调用约定,否则您无法通过更改脚本的任何内容来修复此错误,因为问题是在 shell 尝试启动它时发生的!

但是,还有另一种解决方法 - 您可以将其定义为 shell 函数(在您的 ~/.bashrc 或类似中),而不是将其定义为外部脚本,这意味着它不需要作为外部脚本启动命令,这意味着有问题的操作系统限制不适用。

checkres() {
  for img; do
    ...
  done
}
checkres *.jpg

...完全在 shell 中执行,对命令行长度的任何限制都可以在执行期间传递给外部命令。

【讨论】:

  • ./checkres.sh:第 19 行:语法错误:文件意外结束
  • @newbtard,哦——我想我找到了你的语法错误的原因;我在评论中给出的一些代码中有太多引号(错别字,sigh)。 read width height < <(identify -format '%w %h\n' "$img") 是更正后的形式。
  • 你还不如直接在脚本里做for img in *.jpg。否则,checkres *.jpg 将产生巨大的开销:通配(很长),然后需要复制所有参数以传递给checkres,然后循环。这将产生巨大的开销!
  • @gniourf_gniourf,我同意 globbing 是昂贵的(比让 find 这样做更昂贵,因为 shell 将 glob 结果排序为排序顺序),但复制到 /来自 argv 在现代硬件上真的很重要吗?我想不出一个我曾经注意到它的例子。
  • @gniourf_gniourf,因为性能几乎完全取决于调用identify 命令的时间量,我认为在几十万的过程中不会有几秒钟的差异文件在这里很重要。但这一个很好的观点,我正在修改我的心智模型。
【解决方案2】:

如果你想要一个目录参数:

for img in "$1"/*; do

以这种方式正确引用将确保您的代码可以处理包含空格的目录名称。

【讨论】:

  • 谢谢,如果我能正常工作,我会再试一次并发布它;)
猜你喜欢
  • 2021-03-28
  • 1970-01-01
  • 2020-05-08
  • 2019-03-25
  • 1970-01-01
  • 1970-01-01
  • 2019-06-03
  • 2017-11-30
  • 2020-05-09
相关资源
最近更新 更多