【问题标题】:While read line is very slow虽然读取线很慢
【发布时间】:2013-09-24 23:21:57
【问题描述】:

我想为大量图像创建拇指。 问题是,对于大型列表,读取行似乎非常慢。我能想到的一种解决方案是创建最多包含 500 行的文件,然后一一读取。但是这个问题有什么聪明的解决方案吗?

while read line; do
  if [ -e "$line" ] && [ ! -z "$line" ]; then
              ...
  fi
}
done <<< "$imagesList"

【问题讨论】:

  • 也许使用比 bash 更适合这些任务的东西?
  • 另外,你从哪里得到$imagesList,你为什么用&lt;&lt;&lt;传递它?也许您可以将创建该列表的任何内容通过管道传输到xargs
  • 高度怀疑这里的慢是阅读这些行。您正在为每个文件创建缩略图? 那是缓慢的部分。
  • 我的直觉是缓慢的部分是从find 命令构建长字符串,然后再次将其拆分为行。请改用find ... | (while read line; do; ...; done)
  • 无意冒犯,但这个评论线程充满了货物崇拜,并且从问题中没有足够的可观察性来真正确认或否认任何方法。很可能find … -exec something {} + 是比涉及while loop任何事情 更合适的方法,但如果问题中没有更多信息,就不可能组成该答案。

标签: linux bash loops while-loop


【解决方案1】:

您的问题是您使用 HERE 字符串通过 &lt;&lt;&lt; 读取这些行。如果 HERE 字符串很大,这会很慢。

如果$imgageList是一个文件,你可以做一个文件重定向,这样会快很多:

while read line
do
    if [ -e "$line" -a ! -z "$line" ]
    then
       ...
    fi
done < "$imagesList_file"  # Redirect from a file.

你也许可以这样做:

echo "$imagesList" | while read line
    do
    if [ -e "$line" -a ! -z "$line" ]
    then
       ...
    fi
done

但是,我会担心命令行超载。在 Linux/Unix 系统中,这是在 /usr/include/sys/syslimits.h/usr/include/syslimits.h 中定义的。在我的系统上是 1024 * 256 或 262,144 字节。这听起来很多,但可能具有欺骗性。文件名可能很长——尤其是如果您在其中包含目录路径。这通常足够长,可以在您进行测试时通过,但在您真的非常依赖它来工作时会失败。和。它默默地失败了。你永远不知道最后几个文件名被删除了。

最好的办法是创建一个包含图像名称列表的文件,而不是将它们加载到环境变量中。

【讨论】:

  • 在命令行重载what? ARG_MAX 是传递给exec 的缓冲区的最大长度,如果您可以避免使用子shell,它不应该影响纯bash 解决方案。如果你确实创建了一个子shell,我认为echo | while read 的速度非常值得怀疑,因为你还有PIPE_BUF 限制了管道的缓冲区大小。
  • ARG_MAX 也是命令行可以容纳的最大长度——一旦命令行被扩展。 shell 扩展命令行并将其传递给命令。如果$imagesList 很大,则可能太大而无法传递给正在执行的命令。 PIPE_BUF 不是一个限制因素。事实上,在我的系统上,它只有 512 个字节。 PIPE_BUF 用于将第一个命令的 STDOUT 的数据保存到第二个命令的 STDIN(如果第二个命令尚未准备好)。我当然可以通过管道传递超过 512 个字节。
  • 我不是说PIPE_BUF 限制了数量,只是限制了速度。但是让我们忽略这一点。这里更关键的是ARG_MAX shell 通过exec 调用某些东西时可以容纳在命令行中的最大长度。如果 shell 正在调用内置函数,例如在循环中,ARG_MAX 不适用。就像这里的情况一样。
【解决方案2】:

让我们再试一次:

echo $imagelist | xargs --delimiter=\  --max-args=1 -i echo "Do something with {}"

--- 8

试试这样的:

for IMG in $imageList; do
    echo "Do something with ${IMG}"
done

--- >8 第一版 --- >8 ---

【讨论】:

  • 如果$imageList 和 OP 所说的一样大,这将非常慢,并且可能会使命令行过载,这意味着最后的条目将不会被执行。
猜你喜欢
  • 2014-11-27
  • 1970-01-01
  • 1970-01-01
  • 2021-02-17
  • 1970-01-01
  • 1970-01-01
  • 2020-11-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多