Converting RAR to ZIP in Linux
As ever, mostly notes to myself.
RAR is a silly and proprietary format. I prefer free software and I find that ZIP files are smaller and decompress faster. Not everyone agrees, and that's fine. Assuming you've downloaded a RAR file and want to convert it to ZIP, what's the easiest way?
Install P7Zip
sudo apt-get install p7zip-full p7zip-rar
Script
This basic bash script will
- Extract a RAR
example.rar
file to a temporary directory on a RAM disk. - Recompress to
example.zip
. - Delete the temporary directory.
Easy!
It is based on this conversion from CBR to CBZ.
BASH#!/bin/bash
echo "Converting RARs to ZIPs"
# Separate files using ␜ http://graphemica.com/%E2%90%9C.
IFS="␜"
# Use RAM disk for temporary files.
WORKDIR="/dev/shm/"
# Set name for the temp dir. This directory will be created under WORKDIR
TEMPDIR="rar2zip"
# Run using "./rar2zip.sh /full/path/to/files/"
# If no directory is specified, then use the current working directory (".").
if test -z $1; then
SOURCEDIR=`pwd`
else
SOURCEDIR="$1"
fi
echo "Using $SOURCEDIR"
# Create an temporary directory to work in.
cd $WORKDIR
mkdir $TEMPDIR
cd $TEMPDIR
# Find all the .rar files in the specified directory.
# Using -iname means it will find .rar .RAR .RaR etc.
# "-printf "%p␜" will cause the file names to be separated by the ␜ symbol,
# rather than the default newline.
for OLDFILE in `find $SOURCEDIR -iname "*.rar" -printf "%p␜"`; do
# Get the file name without the extension
BASENAME=`basename "${OLDFILE%.*}"`
# Path for the file. The ".zip" file will be moved there.
DIRNAME=`dirname $OLDFILE`
# Name of the .zip file
NEWNAME="$BASENAME.zip"
# Create a temporary folder for unRARed files
echo "Extracting $OLDFILE"
mkdir "$BASENAME"
7z x "$OLDFILE" -O"$BASENAME"
cd "$BASENAME"
# Zip the files with maximum compression
7z a -tzip -mx=9 "$NEWNAME" *
# Alternative. MUCH SLOWER, but better compression
# 7z a -mm=Deflate -mfb=258 -mpass=15 -r "$NEWNAME" *
# Move the new .zip to the directory containing the original ".rar" file
mv "$NEWNAME" $DIRNAME/"$NEWNAME"
# Delete the temporary directory
cd $WORKDIR
rm -r "$BASENAME"
# OPTIONAL. Delete the RAR file
# cd $DIRNAME
# rm "$OLDFILE"
done
# Delete the temporary directory
cd $WORKDIR
rm -r $TEMPDIR
echo "Conversion Done"
That's it! I suppose it might be nice if there were a simpler way to do it - but this is fairly quick and error-proof.
Jay says:
🙁
~/bin/test$ bash -x ../rar2zip.sh * + echo 'Converting RARs to ZIPs' Converting RARs to ZIPs + IFS=␜ + WORKDIR=/dev/shm/ + TEMPDIR=rar2zip + test -z BabyGroot.rar + SOURCEDIR=BabyGroot.rar + echo 'Using BabyGroot.rar' Using BabyGroot.rar + cd /dev/shm/ + mkdir rar2zip + cd rar2zip ++ find BabyGroot.rar -iname '*.rar' -printf %p␜ find: ‘BabyGroot.rar’: No such file or directory + cd /dev/shm/ + rm -r rar2zip + echo 'Conversion Done' Conversion Done
Jay says:
I found my issue. I was giving a file wildcard not a path. The path also has to be absolute since the script does a "cd" within it. Thanks for sharing
Terence Eden says:
Glad you got it working 🙂
FeRD (Frank Dana) says:
I took this idea and made a few updates, including addressing the issues in the comments here.
https://gist.github.com/ferdnyc/e3147aa07fd4770ca66a98f19097f7e6
No longer changes directory Takes filenames as arguments, instead of a directory -- can be given multiple files, so if you want to use wildcard(s) just rar2zip.sh /home/me/Downloads/.rar /home/me/Downloads/.RAR Quotes all variables to protect paths with spaces in them Uses
mktemp
to create a new temporary directory for each extraction Usesrar
to extract (my 7z command couldn't read rar files, ymmv) Writes the output file in-place, instead of moving it Preserves .rar file modification time on .zip Refuses to overwrite existing destination files Usesgio trash
instead of rm, to remove the source file@edent says:
Awesome, thanks!
Robert Benson says:
Thanks for this, I ended up needing to also remove a top level directory from the contents of a RAR file before making the ZIP, so I made a modified version of this script. It also targets a single file instead of looping over a whole directory https://github.com/derelbenkoenig/bash-fu/blob/master/bin/rar2zip