進行中に削除する再帰的なUnrar

進行中に削除する再帰的なUnrar

基本的に、.rar で常にいっぱいになっているディレクトリのセットがあり、残りの .(rar|rXX) ファイルを自動的に削除して、それらを所定の場所で抽出できるようにする必要があります。どうすればよいでしょうか?

注: 完了したらすべてを削除することはできません。スクリプトが 1 つの rar セットを完了すると、それらを削除する必要があります。

ディレクトリ構造の例:

/
/folder1/
        /file1.rar
        /file1.r00
        /file1.r01
/folder2/
        /sub.folder1/
                    /file2.part001.rar (contains a directory "file2")
                    /file2.part002.rar
                    /file2.part003.rar
        /sub.folder2/
                    /file3.rar
                    /file3.r00
                    /file3.r01

期待される結果:

/
/folder1/
        /file1.ext
/folder2/
        /sub.folder1/
                    /file2/
                          /file2.ext
        /sub.folder2/
                    /file3.ext

答え1

Bash のバリアント:

#!/bin/bash
if [ ! -d "${1}" ]; then
    printf '%s: error: mandatory argument is not a valid directory.' "${0##*/}" 1>&2
    exit 1
fi

shopt -s extglob
for i in "${1}"/**/*.rar; do
    cd -- "${i%/*}"
    file=${i##*/}
    unrar e -- "${file}" && rm -- @(${file}|${file%.rar}.r[[:digit:]][[:digit:]])
    cd - >/dev/null
done

RARアーカイブも「合法的に」例えばなどと名付けられる可能性がありmyarchive.part001.rar、そのような種類のアーカイブが存在する場合は、何らかの方法で個別に処理する必要があります。これを解決する実用的な方法は、

unrar e -- "${file}" && rm -- @(${file}|${file%.rar}.r[[:digit:]][[:digit:]])

unrar e -o- -- "${file}"
if [ $? -eq 0 -o $? -eq 10 ]; then
    rm -- @(${file}|${file%.rar}.r[[:digit:]][[:digit:]])
fi

ただし、エラー コード 10 (「抽出するファイルがありません」) が返された場合でも、この方法では RAR ファイルが削除されるため、変更されていない形式では一般に推奨されないことに注意してください。


全体的には、素材をアーカイブ形式で保存しておき、使用したいときにオンザフライ解凍などを使用する方がよいかもしれません。アーカイブ形式を維持することには、他にも利点があるかもしれません。

答え2

これは思いつきで書いているので、テストされていないコードですが、正しい方向に進んでくれるはずです。基本的には、指定したツリーをたどって .rar ファイルを探します。.rar ファイルを見つけると、unrar が非ゼロを返さない限り、その場で解凍して元のアーカイブを削除します。フォルダーに到達すると、関数は自分自身を呼び出し、再帰的になります。

#!/bin/bash

[[ ! -d "$1" ]] && echo "Please point me at a directory!" && exit 1

function recursively_extract_all_rars_in() {
    local x=`pwd` f
    cd "$1"


    for f in (*); do
        [[ -d "$f" ]] && recursively_extract_all_rars_in "$f"
        [[ -f "$f" ]] && [[ "$f" =~ "*.rar" ]] && unrar e "$f" && rm ${f%%.*}.r??
    done
    cd "$x"
}

recursively_extract_all_rars_in "$1"

関数名は完全に任意です。引数を付けて呼び出されたときに、正しい英語のように読めるようにしたいです。[[ -d /path ]]パスが存在し、ディレクトリの場合は true を返します。-fファイルの場合も同様の処理を行います。は、[[ "string" =~ "pattern"]]文字列のパターン マッチングを可能にする bashism です。ほとんど glob パターンと同じように機能します。

この行はlocal x=pwd fわかりにくいかもしれませんが、単に 2 つのローカル変数を定義しているだけです。1 つは を保持するための x という変数でpwd、もう 1 つは初期化されていない f という変数です (これは以下の for ループで初期化されますが、ここではローカルになるように宣言しているだけです)。

を保存しpwd、関数が使用する場合、それを返すことcdは良いことです (tm)。

の出力をlsプログラムで使用するのは一般的に悪いモジョなので、それを避けて、 を使用する必要があることに注意してくださいfindファイル名にスペースが含まれている場合、スクリプトで ls を使用すると大きな問題が発生します。警告されました。

翻訳

Bashで同じことができるかどうかはわかりませんが、ZSHでは、次の行をどこかに記述します。.zshrc

function recursive_unrar() {
    for f in **/*.rar; do
        local cwd=`pwd` fbn=${f##*/}
        cd "${f%/*}"
        unrar e "$fbn"
        rm "${fbn%%.*}.r{01..99} $fbn"
        cd "$cwd"
    done
}

そして、対応するフォルダー内から呼び出すだけです。

関連情報