0

多数のサブディレクトリを含むディレクトリがあり、そのうちのいくつかにはいくつかの zip ファイルが含まれています。ディレクトリを調べて「Archive-foo」という名前を探してサブディレクトリに入るbashスクリプトを作成しようとしています。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
4

2 に答える 2

3

バーマーの答えは鼻の問題にぶつかりました。ループ ヘッダーとして使用for file in $(...)するのはあまり良い考えではありません。

  • それは遅いです: シェルは$(..)最初にあるものを実行し、次にforループを実行します。for終了するまで開始できません$(...)
  • コマンドラインバッファをオーバーランする可能性があります。シェルが実行$(..)され、コマンドラインに配置されます。コマンド ライン バッファーは約 32 キロバイトで、現在はそれ以上かもしれませんが、10,000 個のファイルがあり、各ファイルが平均 20 文字の場合、コマンド ライン バッファーは 200Kb を超えます。
  • for ループは不適切なファイル名の処理が苦手です。ファイル名に空白が含まれている場合、各単語はファイルのように扱われます。

はるかに優れた構成は次のとおりです。

find . ... -print0 | while read -d $\0 file
do
   ...
done
  • これにより、の実行while read中にループを実行できるため、処理findが高速になります。
  • これにより、コマンド ライン バッファーがオーバーランすることはありません。
  • 最も重要なことは、この構文がほぼすべてのタイプのファイル名を処理することです。は、文字 (ファイル名に使用できない文字) でfind区切られた各ファイルを返します。NULは、文字がファイル名間の区切り文字であることをコマンドに-d $\0伝えます。これにより、ファイル名のスペース、タブ、さらには改行も処理されます。readNUL

またfind、非常に柔軟です。リストをファイルのみ、特定の年齢範囲のファイルなどに制限できます。forループを交換するために必要な最も一般的なものは次のとおりです。

$ find . -depth 1

のように動作しls -aます:

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

と同じようlsに動作し、で始まるファイル名をスキップします.

于 2013-07-26T22:46:32.157 に答える