web-dev-qa-db-ja.com

進行中の削除を伴う再帰的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
Jharwood

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ファイルがクリーンアップされるため、変更されていない形式では一般的に推奨されないことに注意してください。


全体として、単に資料をアーカイブ形式で保存し、代わりにオンザフライの解凍などを使用する方がよい場合があります。アーカイブされた形式を維持することには他の利点があるかもしれません。

3

私はこれを頭のてっぺんから書いているので、テストされていないコードですが、正しい軌道に乗るはずです。基本的に、ポイントしたツリーを歩き、.rarファイルを探します。 1つが見つかると、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です。ほとんどの場合、グロブパターンと同じように機能します。

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

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

lsの出力をプログラムで使用することは、一般的にBad Mojoであり、findを優先して、害虫のように回避する必要があることに注意してください。 ファイル名のいずれかにスペースが含まれている場合、スクリプトでlsを使用すると、かなりの時間がかかります。警告が表示されました。

ZSH

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
}

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

1
mkaito