【问题标题】:Bash for loop not working over large dataset in OSXBash for 循环不适用于 OSX 中的大型数据集
【发布时间】:2013-07-27 06:46:32
【问题描述】:

我有一个包含大量子目录的目录,其中一些子目录中有几个 zip 文件。我正在尝试编写一个 bash 脚本,它将遍历目录并查找名称“Archive-foo”进入子目录,如果它包含 zip 文件,请将它们解压缩,然后将 zip 文件丢弃。

我编写的脚本适用于我的测试目录(5 个子目录),但是当我尝试在主存档目录(1200 多个子目录)上使用它时,它无法执行任何操作。

for 循环可以循环通过的最大项目数吗?

这是我的代码

#!/bin/bash
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
NUMBER=0
for i in $( ls )
do
#echo "$i"" is in the Top Level"
NUMBER=$[NUMBER+1]
if ($(test -d "$i")) 
then
    #echo "$i"" is a Directory"
    if [[ "$i" == *Archive* ]]
    then
        #echo "$i"" has Archive in the name"
        cd "$i" 
        unzip -n "*".zip
        mv *.zip ~/.Trash
    #else
        #echo "$i"" does not have Archive in the name"
    fi
 #else
    #echo "$i"" is NOT a Directory skipping"
fi
done
echo "$NUMBER of items"
IFS=$SAVEIFS

【问题讨论】:

    标签: macos bash


    【解决方案1】:

    命令行的大小是有限制的,for i in $( ls ) 可能会超出这个限制。

    试试这个语法:

    ls | while read i;
    do
      ...
    done
    

    唯一的问题是管道在子 shell 中运行 while 循环,因此对 NUMBER 的分配不会持续到原始 shell 进程中。您可以让循环在处理一行时打印一行,并将整个循环通过管道传输到wc -l 以计算行数。

    【讨论】:

      【解决方案2】:

      Barmer 的回答一针见血。使用for file in $(...) 作为循环头不是一个好主意:

      • 速度较慢:shell 先执行$(..) 中的内容,然后运行for 循环。在$(...) 完成之前,它无法启动for
      • 可能会溢出命令行缓冲区:shell 执行$(..),然后将其放到命令行中。命令行缓冲区可能大约 32 KB,现在可能更多,但是如果您有 10,000 个文件并且每个文件平均有 20 个字符,那么您最终会得到超过 200Kb 的命令行缓冲区,
      • For 循环在处理错误的文件名方面非常糟糕:如果文件名中包含空格,则每个单词都会被视为一个文件。

      一个更好的结构是:

      find . ... -print0 | while read -d $\0 file
      do
         ...
      done
      
      • 这可以在执行find 的同时执行while read 循环,使其更快。
      • 这不会超出命令行缓冲区。
      • 最重要的是,这个结构几乎可以处理任何类型的文件名。 find 将返回由 NUL 字符分隔的每个文件 - 一个不能在文件名中的字符。 -d $\0 告诉read 命令NUL 字符是文件名之间的分隔符。这会处理文件名中的空格、制表符,甚至是新行

      find 也非常灵活。您可以将列表限制为仅包含文件、特定年龄范围内的文件等。替换for 循环所需的最常见的是:

      $ find . -depth 1
      

      就像ls -a:

      $ find . \! -name ".*" -prune -a  -depth 1
      

      ls 类似,会跳过以. 开头的文件名。

      【讨论】:

      • 我在使用 find 命令时遇到的唯一问题是将所有文件解压缩到运行 find 命令的目录中。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-13
      • 1970-01-01
      • 1970-01-01
      • 2021-10-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多