我有一个包含大量子目录的目录,其中一些子目录中包含多个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
答案 0 :(得分:3)
命令行的大小有限制,for i in $( ls )
可能超出它。
请尝试使用以下语法:
ls | while read i;
do
...
done
唯一的问题是管道在子shell中运行while
循环,因此NUMBER
的赋值不会持久存储到原始shell进程中。你可以让循环在处理一行时打印一行,并将整个循环传递给wc -l
以计算行数。
答案 1 :(得分:3)
Barmer回答了问题。使用for file in $(...)
作为循环标题不是一个好主意:
$(..)
中的内容,然后运行for
循环。在for
完成之前,它无法启动$(...)
。$(..)
然后将其放在命令行上。命令行缓冲区可能大约是32千字节,现在可能更多,但是如果你有10,000个文件而且每个文件平均有20个字符,那么最终会有超过200Kb的命令行缓冲区,更好的结构是:
find . ... -print0 | while read -d $\0 file
do
...
done
while read
时执行find
循环,使其更快。find
将返回由NUL
字符分隔的每个文件 - 不能是文件名的字符。 -d $\0
告诉read
命令NUL
字符是文件名之间的分隔符。这样可以处理文件名中的空格,制表符甚至新行。 find
也非常灵活。您可以将列表限制为仅限文件,特定年龄范围内的文件等。重放for
循环所需的最常见的是:
$ find . -depth 1
就像ls -a
:
$ find . \! -name ".*" -prune -a -depth 1
行为与ls
类似,并会跳过以.
开头的文件名。