So, I forayed into creating a batch file to recompress lots of zip or rar files into the slightly higher compressed 7zip format. This is was to more tightly compact lots of random zip files I have in various places, and to stop Windows not helpfully searching them slowly whenever I did a search (I bet I can disable it, but it is useful for some vary limited amount of zip files). You’ll need the 7zip program to do this, and most of the examples here should be easily modifiable to suit needs. Yes, batch files are old
but I don’t have another working scripting language handily installed.
These are also very basic batch files. They don’t contain confirmations or much in the way of error checking besides what I describe below, so be careful if you do use them. Run the files from the directory you want the script to work on, in Windows XP you can just double click on the .bat files to do this (it’ll also pause at the end of execution just in case you want to re-read anything).
Basic Compression
Relearning the batch scripts, here we go
First, I got this up and running:
REM Test1.bat Batch file to run 7zip on a folder to 7zip it "C:\Program Files\7-Zip\7z" a -t7z testarchive.7z testarchive\ pause
It did what it says on the tin – my sample folder was compressed. I wanted to check what it compressed – in this case, it created a 7zip file with the testarchive folder in addition to it’s contents. This is what I want to avoid
For extracting files, there was a good example in the actual 7zip help file:
REM Test2.bat - extracting files "C:\Program Files\7-Zip\7z" x *.zip -o* pause
Worked fine on my sample of zip files, for instance, my ASTROFC.zip file with one ASTROFC.exe file in it got extracted to the subdirectory ASTROFC (ending up with the file ASTROFC\ASTROFC.exe available). I need a specific file, so I test this line too:
REM Test3.bat - testing extracting one file "C:\Program Files\7-Zip\7z" x ASTROFC.zip -o"ASTROFC.zip contents" pause
Works perfectly – I want to make sure it is some folder with a post or prefix, since other folders might have already been extracted (I tend to leave them around sometimes). This means no accidental deletes will happen.
The For Loop
So, onto the For loop. The page here was pretty useful. I’ve only made a few necessary batch files before, and not needed many loops.
My For loop at first should print out the filenames that I want to work on, as I’m going for rar and zip, we have:
REM Test4.bat - tell me what rar and zip files are in the current directory. for %%X in (*.rar *.zip) do echo %%X pause
Worked fine! Now a final thing is to get just the filename with no extension for the final 7zip file itself. The Microsoft site helps with this (with that, I also rename the variable "X" with "F" for file):
REM Test5.bat - tell me what rar and zip files are in the current directory with no extension. for %%F in (*.rar *.zip) do echo %%~nF pause
This just omitted any .rar or .zip extensions – will be useful in a bit. Finally, we want it to extract these folders using 7zip to the "*filename* contents" folders:
REM Test6.bat - unzip all the zip and rar files into "*filename* contents" folders for %%F in (*.rar *.zip) do "C:\Program Files\7-Zip\7z" x "%%F" -o"%%F contents" pause
This produced the required folders (eg: "ASTROFC.zip contents" as described above). Now to do this along with compressing the files:
REM Test7.bat - unzip all zips and rars. Create new 7z files from the same names. for %%F in (*.rar *.zip) do "C:\Program Files\7-Zip\7z" x "%%F" -o"%%F contents" for %%F in (*.rar *.zip) do "C:\Program Files\7-Zip\7z" a -t7z "%%~nF".7z "%%F contents\" pause
Now, this successfully created the right archives, with the right files (with default compression settings, which I’ll get to changing in a bit), but there is still the problem of it also adding the top level folder "filename contents" to the archive. I need to fix this! Currently it uses simply the archive "a" command’s "this folder and it’s contents" parameter.
REM Test9.bat - loop, try with no subfile directory for %%F in (*.rar *.zip) do "C:\Program Files\7-Zip\7z" x "%%F" -o"%%F contents" for %%F in (*.rar *.zip) do ( CD "%%F contents" "C:\Program Files\7-Zip\7z" a -t7z "../%%~nF.7z" * CD .. ) pause
I learned how to do multiple things in a do command – ( ) seems to work. Silly how I didn’t find that until some random page on call, which I could have used I guess, showed me.
With that, I can start to merge some bits. But first, I need to delete both the original zip file, and the "filename contents" folder. To do this, using DEL and RMDIR. See this code for notes, and the links for more.
REM Test10.bat - del and deltree to remove the archive REM /F is "Force if read only" and /Q is "Quiet" - no confirmation DEL testarchive.zip /F /Q REM /S is also "Subdirectories" and /Q is "Quiet" - no confirmation RMDIR testarchive /S /Q pause
So now I can use this, pretty easily. Putting this all together we have:
REM Test11.bat - putting it all together. for %%F in (*.rar *.zip) do ( REM Extract... "C:\Program Files\7-Zip\7z" x "%%F" -o"%%F contents" REM Change directory, create 7zip of contents of directory... CD "%%F contents" "C:\Program Files\7-Zip\7z" a -t7z "../%%~nF.7z" * CD .. REM Delete the old files DEL "%%F" /F /Q RMDIR "%%F contents" /S /Q ) pause
It works! It creates identically named files but 7zip archives, using the standard routines. Then deletes the old files and the temp directory. At first, it didn’t work properly since I missed quotes for the DEL and RMDIR commands, oops! Added them back in fast. Okay, now to add some additional stuff…
Additional Nice Stuff
What if the zip isn’t correctly extracted? a "filename contents" folder won’t be created. Therefore, if I run the "create 7zip" part, 7zip compressing will, after testing, just run on the root directory since the CD "filename contents" will fail – and also put it on the folder below the current one (in my case, the root of my drive). Then the rest of the script fails since it is in the root of the drive and not a subdirectory (ouch!). I’ll use a quick if statement to stop this using the "exists" command just to make sure. I’m not going to add too many error checking things (which could check for the 7zip’s exit code among other bits) because for my limited needs, I don’t need a fully automated solution.
REM Test12.bat - adding "If" error checking for %%F in (*.rar *.zip) do ( REM Extract... "C:\Program Files\7-Zip\7z" x "%%F" -o"%%F contents" REM Does the directory exist? has 7zip created it correctly? IF EXIST "%%F contents" ( REM Change directory, create 7zip of contents of directory... CD "%%F contents" "C:\Program Files\7-Zip\7z" a -t7z "../%%~nF.7z" * CD .. REM Delete the old files DEL "%%F" /F /Q RMDIR "%%F contents" /S /Q ) ) pause
I also want to make it look nicer. I don’t need every command shown on the command line – without the command @ECHO OFF even my REM statements get sent to the command line. If I ever want to debug, turning off this by removing this line at the top of the file is pretty easy (although 7zip’s output carries on). So here we go, some ECHO comments added too:
@ECHO OFF REM Test13.bat - echo comments ECHO Searching for RAR and ZIP files to recompress into 7zip archives. for %%F in (*.rar *.zip) do ( ECHO Found %%F to recompress... REM Extract... "C:\Program Files\7-Zip\7z" x "%%F" -o"%%F contents" REM Does the directory exist? has 7zip created it correctly? IF EXIST "%%F contents" ( REM Change directory, create 7zip of contents of directory... CD "%%F contents" "C:\Program Files\7-Zip\7z" a -t7z "../%%~nF.7z" * CD .. REM Delete the old files DEL "%%F" /F /Q RMDIR "%%F contents" /S /Q ECHO Recompressed %%F to %%~nF.7z and deleted %%F. ) ) ECHO Search ended. pause
Finally, I want to compress the 7zip archives to maximum quality. This is quite easy, and is stated pretty easily in the manual – it’s just the addition of -mx=9 (-m being "modifiers", x being "level of compression" and we want it to be 9, the maximum, so "=9"). This last addition makes it pretty much complete, so I rename the script to zip_7zip_automated_delete.bat, ready to be copied
@ECHO OFF REM zip_to_7zip_automated_delete.bat - find all .zip and .rar files in the current directory, recompress them into 7zip files and delete the originals. Skip ones that don't decompress. ECHO Searching for RAR and ZIP files to recompress into 7zip archives. for %%F in (*.rar *.zip) do ( ECHO Found %%F to recompress... REM Extract... "C:\Program Files\7-Zip\7z" x "%%F" -o"%%F contents" REM Does the directory exist? has 7zip created it correctly? IF EXIST "%%F contents" ( REM Change directory, create 7zip of contents of directory... CD "%%F contents" "C:\Program Files\7-Zip\7z" a -t7z "../%%~nF.7z" * -mx=9 CD .. REM Delete the old files DEL "%%F" /F /Q RMDIR "%%F contents" /S /Q ECHO Recompressed %%F to %%~nF.7z and deleted %%F. ) ) ECHO Search ended. pause
Whew! Now .zip and .rar files can be all be recompressed in a directory automatically at maximum settings.
Separate 7zip creation and deletion of zip files
Finally, the one thing I wanted to make sure was that the 7zip files got created successfully and delete the zip files only then. The easiest way to do this was from another batch file, but first needing to remove the DEL and DELTREE from the original.
@ECHO OFF REM zip_to_7zip.bat - find all .zip and .rar files in the current directory, recompress them into 7zip files - but don't delete the originals. ECHO Searching for RAR and ZIP files to recompress into 7zip archives. for %%F in (*.rar *.zip) do ( ECHO Found %%F to recompress... REM Extract... \"C:\Program Files\7-Zip\7z\" x \"%%F\" -o\"%%F contents\" REM Does the directory exist? has 7zip created it correctly? IF EXIST \"%%F contents\" ( REM Change directory, create 7zip of contents of directory... CD \"%%F contents\" \"C:\Program Files\7-Zip\7z\" a -t7z \"../%%~nF.7z\" * -mx=9 CD .. REM Delete the temporary extraction folder RMDIR \"%%F contents\" /S /Q ECHO Recompressed %%F to %%~nF.7z ) ) ECHO Search ended. pause
Then move them to their dedicated file as below:
@ECHO OFF REM zip_automated_delete.bat - find all .zip and .rar files in the current directory delete them if a \"filename.7z\" file exists for them in the same directory. ECHO Searching for RAR and ZIP files to delete for %%F in (*.rar *.zip) do ( ECHO Found %%F to possibly delete... REM Check IF EXIST \"%%~nF.7z\" ( REM Delete the old file, we have a copy DEL \"%%F\" /F /Q ECHO Found %%~nF.7z so can delete %%F. Deleted. ) ELSE ( ECHO Cannot delete %%F, no %%~nF.7z file found. ) ) ECHO Search ended. pause
Working on Subfolders
I was interested to see if I could get it to work on subfolders as easily as a single folder, although since I don’t add much error checking it might cause some errors, but is useful for running on a large amount of files
In any case, the altered script looks like this to create the files:
@ECHO OFF REM zip_to_7zip_subfolders.bat - find all .zip and .rar files in the current directory and all subfolders, recompress them into 7zip files - but don't delete the originals. set ROOTDIR=%CD% ECHO Searching for RAR and ZIP files to recompress into 7zip archives. for /R "%ROOTDIR%" %%F in (*.rar *.zip) do ( ECHO Found %%F to recompress... REM Extract... "C:\Program Files\7-Zip\7z" x "%%F" -o"%%F contents" REM Does the directory exist? has 7zip created it correctly? IF EXIST "%%~fF contents" ( REM Change directory, create 7zip of contents of directory... CD "%%~fF contents" "C:\Program Files\7-Zip\7z" a -t7z "../%%~nF.7z" * -mx=9 CD "%ROOTDIR%" REM Delete the temporary extraction folder RMDIR "%%~fF contents" /S /Q ECHO Recompressed %%F to %%~nF.7z ) ) ECHO Search ended. pause
And this to delete the zip files, this again makes sure a 7z file of the same name exists:
@ECHO OFF REM zip_subfolders_automated_delete.bat - find all .zip and .rar files in the current directory and all subfolders delete them if a "filename.7z" file exists for them in the same directory. set ROOTDIR=%CD% ECHO Searching for RAR and ZIP files to delete for /R "%ROOTDIR%" %%F in (*.rar *.zip) do ( ECHO Found %%F to possibly delete... REM Check IF EXIST "%%~pnF.7z" ( REM Delete the old file, we have a copy DEL "%%F" /F /Q ECHO Found %%~pnF.7z so can delete %%F. Deleted. ) ELSE ( ECHO Cannot delete %%F, no %%~pnF.7z file found. ) ) ECHO Search ended. pause
Pretty easy changes to the FOR loop parameters luckily, and the change to add in the "Working Directory" backtrack properly too using a variable.
Further Work
Since I only did this as an exercise to save some time, rather then to make anything that’ll stand the test of time, the batch file seriously lacks confirmation, logging and basic statistic parts (such as counting how many things were converted). There is also no "make a comparison" part for checking if I saved space or not (sometimes 7zip files can be bigger then well compressed zip files). At least it works though
Resources
The files: BatchZipTo7Zip.7z (2KB) or BatchZipTo7Zip.zip (7KB) – should be all pretty much as above.
Via. Google searches and bookmarks, I used these webpages:
- http://technet.microsoft.com/en-gb/library/bb491071.aspx – Microsoft documentation. There are poor examples/explanations in places (and some links don’t work?), but the FOR loop documentation was to die for.
- http://www.computerhope.com/batch.htm – nice and basic information, with updates for XP
- http://commandwindows.com/batchfiles-iterating.htm – For loop! Nice intro to it
- http://www.robvanderwoude.com/batchfiles.html – Some random useful stuff here
PS: For Wordpress users, using my normal quote button didn’t work, it kept adding trailing slashes, very odd, had to replace with the quot version. Wonder why it’s not fixed yet?
{ 3 } Comments
Excellent post, this is exactly what I was looking for, many thanks for sharing! I made few changes though – many of my ZIP files are backups with long path names, so the current path + the extracted paths were going over 255 chars and causing errors. I changed the script to always extract the ZIP archive in “F:\1″, and then move the 7z archive to where the original ZIP archive is located.
…
REM Extract…
“C:\Program Files\7-Zip\7z” x “%%F” -o”F:\1″
REM Does the directory exist? has 7zip created it correctly?
IF EXIST “F:\1″ (
REM Change directory, create 7zip of contents of directory…
CD “F:\1″
“C:\Program Files\7-Zip\7z” a -t7z “../%%~nF.7z” * -mx=9
move “..\%%~nF.7z” “%%~pF”
CD “%ROOTDIR%”
REM Delete the temporary extraction folder
RMDIR “F:\1″ /S /Q
…
Cool tip there, I never had large zips to convert (or at least not many files in them) so that’d be very helpful for those that do and have a drive with enough space. Glad you found it useful too, I need to write up a few more simple windows scripts but nothing really this useful, heh.
Nice! I made some changes to my version to add error checking.
Basically I check the ERRORLEVEL returned by the 7zip calls to make sure I am not recompressing bad zip/rar files and 7zip compression part did not fail.
Post a Comment