
以下の3つに示すように、zipファイル内に入れ子になったファイルを含む数千のzipファイルを含む数百の複数のフォルダがあります。
start tree structure
012016/
├── 2016-01
│ └── 2016-01
│ ├── build
│ ├── DOC
│ │ ├── WONWA1
│ │ │ ├── WO1NWA1
│ │ │ │ ├── WO2016000001NWA1.xml
│ │ │ ├── WO1NWA1.zip
│ │ │ ├── WO2NWA1
│ │ │ │ ├── WO2016000002NWA1_tr.xml
│ │ │ ├── WO2NWA1.zip
└── 2016-01.zip
end tree structure
以下にフォルダと内容を再帰的に確認する簡単なスクリプトを作成しました。 zipファイルが見つかったら、内容を抽出し、抽出したフォルダの内容を確認します。
以下のスクリプトを実行しようとすると:
recurse() {
for i in "$1"/*;
do
currentItem="$i"
extension="${currentItem##*.}"
if [ -d "$i" ]; then
#echo "dir: $i"
recurse "$i"
elif [ -f "$i" ]; then
#echo "file: $i"
#echo "ext: $extension"
[[ ${extension} = +(sh|xslt|dtd|log|txt) ]] && break
extractionDirectory=$(dirname $currentItem)/$(basename -s .zip $currentItem )
[[ ${extension} = "zip" ]] && unzip -uq $currentItem -d "${extractionDirectory}"
recurse ${extractionDirectory}
fi
done }
recurse $PWD
ただし、上記のスクリプトを実行すると、次のエラーが発生します。
分割エラー(コアダンプ)
答え1
分割エラーはいくつかの理由で発生する可能性があります。最も一般的な下位レベルの原因は、未定義のメモリアドレスにアクセスしようとしているプロセス、つまり無効なポインタの逆参照です。これは通常プログラムのバグです。
ここではシェルプログラムを実行しています。シェルは高度なプログラミング言語であり、ポインタがないため、スクリプトで誤ったポインタの逆参照が発生することはありません。
多くのプログラムはスペースが限られています。コールスタックスタックサイズを超えたために発生した分割エラーです。ほとんどの場合、スタックサイズの制限は合理的な量のデータに対して十分ですが、無限再帰によりスタックが破損する可能性があります。
Bashでは、関数呼び出しの無限再帰は実際に分割エラーを引き起こす可能性があります。 (dashとmkshも同様です。kshとzshはよりスマートで、シェルレベルで最大関数呼び出しのネスト深さを適用するため、セグフォルトは発生しません。)
スクリプトにいくつかのエラーがあります。あなたをいじめるのは、通常のファイルの場合は、常にrecurse
zipファイルに対してのみ呼び出したい場合は常に最後に呼び出すことです。
またはを意味するときは使用しないでください&&
。あなたが意味するものを書くのがより明確です。あいまいさを通じた簡潔さは良い考えではなく、ここではあなたを悩ませます。||
if
if [[ ${extension} = "zip" ]]; then
unzip -uq $currentItem -d "${extractionDirectory}"
recurse ${extractionDirectory}
fi
もう一つのエラーは、あなたが欠けているということです変数の置換は二重引用符で囲まれています。したがって、プログラムは何よりもスペースを含むファイル名をブロックします。変数置換を省略する必要があることを知らない限り、必ず二重引用符を使用してください。
basename
とを呼び出す代わりに、パラメータ拡張を使用してくださいdirname
。特別な場合(たとえば、で始まるファイル名など-
)を処理する方が簡単で迅速です。
私が見つけたもう一つのバグは、パターンが+(sh|xslt|dtd|log|txt)
明らかに意味することです@(sh|xslt|dtd|log|txt)
(これらの拡張子と一致するshsh
ものではありませんdtdtxtshdtd
)。
case
これは一般的なファイル状況です。上記のエラーは修正され、明確にするために書き直されました。
case "$extension" in
sh|xslt|dtd|log|txt) break;;
zip)
extractionDirectory=$"{currentItem%.zip}"
unzip -uq "$currentItem" -d "${extractionDirectory}"
recurse "${extractionDirectory}"
esac
ロジックを確認したり、コードをテストしていません。書く方法が複雑に見えます。
find -type f -name '*.zip' -exec sh -c 'unzip -uq "$0" -d "${0%.zip}"' {} \;
答え2
~からザイルズの答え:
Bashでは、関数呼び出しの無限再帰は実際に分割エラーを引き起こす可能性があります。 (dashとmkshも同様です。kshとzshはよりスマートで、シェルレベルで最大関数呼び出しのネスト深さを適用するため、セグフォルトは発生しません。)
Bashでは、設定によって最大関数呼び出しのネスト深さを設定することもできますFUNCNEST
。この場所は次のとおりですman bash
。
FUNCNEST変数が0より大きい値に設定されている場合、最大関数入れ子レベルを定義します。制限を超える関数呼び出しにより、コマンド全体が中断されます。
ここで実際に動作する様子を見ることができます:
$ f () { f; }
$ FUNCNEST=10 f
bash: f: maximum function nesting level exceeded (10)