web-dev-qa-db-ja.com

bashで.rarマルチパートを抽出します

私は実行します このスクリプト しかしこれはrarマルチパートの抽出に問題があります

#!/usr/bin/env bash

shopt -s extglob nullglob

passw=(
  passfoo
  passbar
  passfoobar
  banana
  chocolate
  whiskey
  vodka
  icecream
)

for f in *.@(rar|Zip|zip.001|7z|7z.001); do
  for p in "${passw[@]}"; do
    if 7z x -y -p"$p" "$f" -aoa; then
      break
    fi
  done
done

.Zipまたは.7zを使用すると、マルチパートの拡張子が等しいため、マルチパートが適切に解凍されます(.7z = 7z.0017z.002などの場合。.Zip = Zip.001Zip.002の場合)。問題は、これをスクリプトに追加すると、次のようになることです。

*.@(rar|part1.rar|Zip|zip.001|7z|7z.001)

*.partX.rar.rarの両方が。rarで終わり、ファイルにパスワードがある場合、ループは同じものを何度も解凍するか、.part2.rar以降で失敗するため、失敗します。

問題を修正しようとして失敗しました:

  1. .part2.rarからファイルを除外するには(例:*.part{2..99}.rar

  2. スイッチ "-x"

ループを完了し、.rar形式のマルチパートファイルの解凍を統合するのに役立ちます。

3
ajcg

外側のループで最初に行うことは、_$f_がスキップされる資格があるかどうかを確認することかもしれません。

Bashでは、パターンマッチング(_[[_、_=_または_==_)または正規表現(_!=_)のいずれかを使用して、_=~_でこれを行うことができます。後者のオプションはより強力です。あなたの場合、これはうまくいくはずです:

_for f in *.@(rar|Zip|zip.001|7z|7z.001); do
  [[ ( "$f" =~ \.part[[:digit:]]+\.rar$ ) && ! ( "$f" =~ \.part0*1\.rar$ ) ]] && continue
  for p …
_

私が使用した式は、次の部分で構成されています。

  • _\._ –リテラルドットに一致
  • partrar、_1_ –これらはそれぞれ文字通りpartrar、_1_に一致します
  • _[[:digit:]]+_ – 1つ以上の数字に一致します(現在のロケールで定義されているとおり)
  • _0*_ – 0個以上の_0_文字に一致
  • _$_ –テストされている文字列の終わりに一致します

_!_は否定します。

ロジックは次のようになります。ファイル名が.part<digit(s)>.rarで終わり、_.part1.rar_(または_.part01.rar_、または_.part001.rar_など)で終わらない場合は、再開します。次の反復(つまり、次のfを取り、最初からやり直します)。


私があなたなら、nocaseglobを_shopt -s …_行に追加して、_FOO.RAR_のような名前をあなたのパターン(*.@(rar|Zip|zip.001|7z|7z.001))と一致させます。私のテストは、私のソリューション(_=~_)をそれらでも機能させるのに十分であることを示しています(追加でnocasematchを有効にする必要はありません)。

_shopt -s extglob nullglob nocaseglob
_
1