I have a lot of rar files

- Folder/
--- Spain.rar
--- Germany.rar
--- Italy.rar

All the files contains no root folder so it's just files.

What I want to achieve when extracting is this structure:

- Folder/
-- Spain/
---- Spain_file1.txt
---- Spain_file2.txt
-- Germany/
---- Germany_file1.txt
---- Germany_file2.txt
-- Italy/
---- Italy_file1.txt
---- Italy_file2.txt

So that a folder with the name of the archive is created and the archive is extracted to it.

I found this bash example in another thread but it's not working for me, it's trying to create one folder with all the files as name.


for archive in "$(find . -name '*.rar')"; do
  if [ ! -d "$destination" ] ; then mkdir "$destination"; fi
  unrar e "$archive" "$destination"

Any ideas how I can do this?


I have a script in my personal archive that does exactly this. More precisely, it extracts e.g. Spain.rar to a new directory called Spain, except that if all the files in Spain.rar are already under the same top-level directory, then this top-level directory is kept.


# Extract the archive $1 to a directory $2 with the program $3. If the
# archive contains a single top-level directory, that directory
# becomes $2. Otherwise $2 contains all the files at the root of the
# archive.
extract () (
  set -e
  case "$archive" in
    -) :;; # read from stdin
    /*) :;; # already an absolute path
    *) archive=$PWD/$archive;; # make absolute path
  if [ -e "$target" ]; then
    echo >&2 "Target $target already exists, aborting."
    return 3
  case "$target" in
    /*) parent=${target%/*};;
    */[!/]*) parent=$PWD/${target%/*};;
    *) parent=$PWD;;
  temp=$(TMPDIR="$parent" mktemp -d)
  (cd "$temp" && $program "$archive")
  for member in "$temp/"* "$temp/".*; do
    case "$member" in */.|*/..) continue;; esac
    if [ -n "$root" ] || ! [ -d "$member" ]; then
      root=$temp # There are multiple files or there is a non-directory
  if [ -z "$root" ]; then
    # Empty archive
  mv -v -- "$root" "$target"
  if [ "$root" != "$temp" ]; then
    rmdir "$temp"

# Extract the archive $1.
process () {
  case "$1" in
    *.rar|*.RAR) program="unrar x";;
    *.tar|*.tgz|*.tbz2) program="tar -xf";;
    *.tar.gz|*.tar.bz2|*.tar.xz) program="tar -xf"; dir=${dir%.*};;
    *.zip|*.ZIP) program="unzip";;
    *) echo >&2 "$0: $1: unsupported archive type"; exit 4;;
  if [ -d "$dir" ]; then
    echo >&2 "$0: $dir: directory already exists"
    exit 1
  extract "$1" "$dir" "$program"

for x in "$@"; do
  process "$x"

Usage (after installing this script in your $PATH under the name extract and making it executable):

extract Folder/*.rar
  • This looks pretty awesome and I think this is what I need. But I am having trouble getting it to work. There seems to be something wrong with the way unrar is being called. When I run it, I get the usage example. It creates a lot of tmp folders but the extractions fails. What version of unrar did you use this on? – Dennis Wiencken Oct 19 '18 at 12:43
  • @DennisWiencken Evidently I'd never tried this version with anything but zip. Try my fixed version. – Gilles Oct 19 '18 at 13:04
  • Works like a charm now! Thank you for the help! – Dennis Wiencken Oct 19 '18 at 13:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.