web-dev-qa-db-ja.com

コマンドラインのフォルダーに基づいて、ファイルを.cbzファイルに再帰的に圧縮します

OSX上のフォルダ内の画像から.cbzファイルの作成を自動化するスクリプトを作成する方法を理解しようとしています。

私のディレクトリツリーは次のようになります。

/toplevel/
cbz/
comics/
    Comic1/
        comic1file1.jpg
        comic1file2.gif
        comic1file3.png
    Comic2/
        comic2file1.jpg
        comic2file2.gif
    Publisher/
            Comic3/
                comic3file1.jpg
                comic3file2.gif
                comic3file3.png
            Comic4/
                comic4file1.jpg
                comic4file2.gif

そして、私がやりたいのは、サブフォルダーではなく実際のファイルを含むフォルダーを見つけてZipするスクリプトを実行し、名前を.Zipから.cbzに変更して、.cbzファイルをトップレベルの/ cbzフォルダーに移動することです。サブフォルダーを含むフォルダーにはファイルを含めないでください。これが役立つ場合があります。また、上記の例に示されているものよりも深いサブフォルダーが存在することはないと思います。

私がいる場所:このスニペットはフォルダーを調べて、各サブフォルダーの.cbzファイルを作成します。

for dir in `ls`; do Zip $dir $dir/*; mv $dir*Zip $dir.cbz; done

また、選択したフォルダーの下にあるすべてのサブフォルダーと同様のことを行うスニペットをいくつか見つけましたが、結果はさまざまであり、フォルダーに対してのみ操作を実行するための最良の方法を学ぶことに非常に興味があります。また、特定のフォルダーにサブフォルダーまたはファイルが含まれているかどうかを確認する方法についてもわかりません。 (理想的には、両方があるかどうかを確認するためのチェックを含める必要があると思いますが、現在のシナリオではそうではないはずです。)何かアイデアはありますか?

2
Martin

別のわずかに異なる解決策:

#!/bin/bash
find toplevel/comics -type d -not -empty -print0 | while IFS= read -r -d '' dir; do
  if find "$dir" -maxdepth 1 -type f | read f; then
    Zip toplevel/cbz/"$(basename "$dir").cbz" "$dir"/*
  fi
done
  • find … -print0 | while IFS= read -r -d '' file is 推奨パターンfindの結果を反復処理します。簡単なfind … | while read fileは正常に機能しますが、返されたファイル名に改行が含まれていない場合に限ります。 lsの解析は決して推奨されません。

  • find "$dir" -maxdepth 1 -type f | read fファイルがディレクトリに見つかった場合にのみ、trueと評価されます。これは、@ terdonがfindによって出力される行数を評価するのと同じ目的を達成します。

  • ファイル名の空白が引数を壊さないようにするには、すべての変数を引用符で囲む必要があります。

4
slhck

まず第一に、 lsの出力を解析しないでください 。また、作成するアーカイブにZipに任意の名前を付けることができるため、ファイルを移動する必要はありません。これを試して:

find toplevel/comics/ -mindepth 1 -type d | 
while read dir; do 
    num=$(find "$dir" -mindepth 1 -maxdepth 1 -type f | wc -l )  
    [ "$num" -gt "0" ] && Zip toplevel/cbz/"$(basename $dir)".cbd "$dir"/*; 
done

最初のfindコマンドは、toplevel/comics/で、指定されたパス(サブディレクトリ)の少なくとも1レベル下(type -d)にあるディレクトリ(-mindepth 1)を検索します。これにより、findが結果としてtoplevel/comics自体を返さないことが保証されます。その検索結果は、変数$dirに保存されている各ループを処理するwhileループにパイプされます。各$dirは、サブディレクトリ(-type f)ではなく、実際にはそのディレクトリにあるファイル(-mindepth 1 -maxdepth 1)を検索します。 findによって返される行数(wcが行うこと)は$numとして保存され、0より大きい場合、ディレクトリは圧縮され、アーカイブはcbzに配置されます。

注:アーカイブにはファイルへのフルパスが含まれます(ファイルを解凍してテストします)。これが必要ない場合は、-jオプションをZipに指定することをお勧めします。 man Zip を参照してください。

2
terdon