extract .rar multiparts with bash

Posted on

Problem :

i run this script but this have a problem with extract rar multiparts

#!/usr/bin/env bash

shopt -s extglob nullglob


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

With .zip or .7z it decompresses the multiparts well, because the extension of the multiparts are equal (for .7z = 7z.001, 7z.002, etc. For .zip = zip.001, zip.002, etc). The problem is that if I add this to the script:


It fails because *.partX.rar and .rar both end in .rar and the loop unzips the same thing over and over again or fails in .part2.rar onwards if the file has password

Failed attempts to fix the problem:

  1. To exclude any file from .part2.rar (example: *.part{2..99}.rar)

  2. With the switch “-x”

I appreciate help completing the loop and integrating decompression of multipart files in .rar format

Solution :

The first thing to do in the outer loop may be to check if $f qualifies to be skipped.

In Bash you can do this with [[, using either pattern matching (with =, == or !=) or a regex (with =~). The latter option is more powerful. It your case this should work:

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

The expressions I used consist of these parts:

  • . – matches a literal dot
  • part, rar, 1 – these match part, rar and 1 literally, respectively
  • [[:digit:]]+ – matches one or more digits (as defined by the current locale)
  • 0* – matches zero or more 0 characters
  • $ – matches the end of string being tested

! negates.

The logic is like this: if the filename ends with .part<digit(s)>.rar and it doesn’t end with .part1.rar (or .part01.rar, or .part001.rar etc.) then resume the next iteration (i.e. take the next f and start over).

If I were you, I would add nocaseglob to the shopt -s … line, to match names like FOO.RAR with your pattern (*.@(rar|zip|zip.001|7z|7z.001)). My tests indicate it’s enough to make my solution (=~) work with them as well (no need to additionaly enable nocasematch).

shopt -s extglob nullglob nocaseglob

Leave a Reply

Your email address will not be published. Required fields are marked *