So I want to be able to drag one or more rar or zip files to a batch .cmd script that extracts the file with 7zip to a directory one level up, renames the extracted file to the current folder name and then deletes the folder with the rar or zip archives.
So far I have:
set work=%temp%\%random%%random%%random%%random%
mkdir "%work%" || goto :eof
for %%A in (*.zip *.rar) do (
"%ProgramFiles%\7-Zip\7z.exe" e -o"%work%" "%%~A"
for %%F in ("%work%\*") do move "%%~F" "%%~nA%%~xF"
)
rmdir "%work%"
And that extracts the file to the current directory and renames it to the archive name but I want to name it to the directory the archive is in so %%~nA needs to be changed but typing "for /?" doesn't seem to give me an option to get the current directory. Then I need to move the extracted file one level up and delete the folder with the archive files, I just don't know how to reference the files when using move and rmdir when in a loop.
This is my first attempt at batch scripting please go easy on me.
CodePudding user response:
This is going to be more of a lesson on how to do reasonably good programing in *cough* a bad *cough* the batch programming language.
The first stage is to work from the outside inwards, or top down. It only took a few minutes to build this framework. The sub goals/steps are:
- Simply loop through all of the parameters and see if we can save them to a variable and then echo them out.
- Figure out how to extract the SubFolderName (This will later be the file name), and echo it per each loop.
- Build the Extract folder and echo per each loop.
- Realize you forgot you were going to need the folder path of the calling batch file, add it as first parameter, and extract it before entering the :ltpLoop.
The %1 gets the first parameter, while SHIFT will shift all parameters so that %1=%2, %2=%3, %3=%4, %4=%5, etc... This effectively removes the first parameter and reduces the total number of parameters by 1. The IF statement exits the script when SHIFT has removed all parameters and %1 no longer has a value.
Also, a lot of people will follow the ECHO command with a period (ECHO.Text to echo), but I had one bad case where period printed a blank line instead of the text, but semicolon ; was fine - so I no do period, period!
@ECHO OFF
GOTO :Start
:LoopThroughParameters
SET CmdPath=%~1
SHIFT
ECHO;[[[%CmdPath%]]]
:ltpLoop
IF [%1] EQU [] GOTO :EOF
SET Folder=%~1
SET SubFolderName=%~nx1
SET ExtractFolder=%~1\Extract
ECHO;
ECHO;[%Folder%]
ECHO;[%SubFolderName%]
ECHO;[%ExtractFolder%]
SHIFT
GOTO :ltpLoop
:Start
CALL :LoopThroughParameters "%~dp0" %*
PAUSE
In stage 2 we start by cleaning up the code by removing the unneeded echos.
:LoopThroughParameters
SET CmdPath=%~1
SHIFT
:ltpLoop
IF [%1] EQU [] GOTO :EOF
SET Folder=%~1
SET SubFolderName=%~nx1
SET ExtractFolder=%~1\Extract
<<New Code Will Go Here>>
SHIFT
GOTO :ltpLoop
Start experimenting in the <<New Code Will Go Here>> area.
ECHO;FOR %%C IN ("%Folder%\*.zip" "%Folder%\*.rar") DO (
The code is tested by creating 5 folders, with one zip file in each folder, and dragging the folders on to the batch file and seeing if we like the commands it built.
FOR %C IN ("D:\Temp\StackOverflow\71345433\volume5\*.zip" "D:\Temp\StackOverflow\71345433\volume5\*.rar") DO (
FOR %C IN ("D:\Temp\StackOverflow\71345433\volume1\*.zip" "D:\Temp\StackOverflow\71345433\volume1\*.rar") DO (
FOR %C IN ("D:\Temp\StackOverflow\71345433\volume2\*.zip" "D:\Temp\StackOverflow\71345433\volume2\*.rar") DO (
FOR %C IN ("D:\Temp\StackOverflow\71345433\volume3\*.zip" "D:\Temp\StackOverflow\71345433\volume3\*.rar") DO (
FOR %C IN ("D:\Temp\StackOverflow\71345433\volume4\*.zip" "D:\Temp\StackOverflow\71345433\volume4\*.rar") DO (
Then we try to build the extraction commands:
FOR %%C IN ("%Folder%\*.zip" "%Folder%\*.rar") DO (
ECHO;"%ProgramFiles%\7-Zip\7z.exe" e -o"%ExtractFolder%" "%%~C"
)
Check if results look correct:
"C:\Program Files\7-Zip\7z.exe" e -o"D:\Temp\StackOverflow\71345433\volume5\Extract" "D:\Temp\StackOverflow\71345433\volume5\Last Zip file.zip"
"C:\Program Files\7-Zip\7z.exe" e -o"D:\Temp\StackOverflow\71345433\volume1\Extract" "D:\Temp\StackOverflow\71345433\volume1\SomeZipFile.zip"
"C:\Program Files\7-Zip\7z.exe" e -o"D:\Temp\StackOverflow\71345433\volume2\Extract" "D:\Temp\StackOverflow\71345433\volume2\JustAnotherZip.zip"
"C:\Program Files\7-Zip\7z.exe" e -o"D:\Temp\StackOverflow\71345433\volume3\Extract" "D:\Temp\StackOverflow\71345433\volume3\YetAnotherZip.zip"
"C:\Program Files\7-Zip\7z.exe" e -o"D:\Temp\StackOverflow\71345433\volume4\Extract" "D:\Temp\StackOverflow\71345433\volume4\How Many Zips Was This.zip"
In stage 3 we try it for real - remove the echo:
"%ProgramFiles%\7-Zip\7z.exe" e -o"%ExtractFolder%" "%%~C"
Check if we like the results (You can see I'm using some old latitude-e5440 PDFs I happen to find in a forgotten folder someplace):
D:\Temp\StackOverflow\71345433>dir /s /b
D:\Temp\StackOverflow\71345433\DragDropAndExtract.CMD
D:\Temp\StackOverflow\71345433\volume1
D:\Temp\StackOverflow\71345433\volume2
D:\Temp\StackOverflow\71345433\volume3
D:\Temp\StackOverflow\71345433\volume4
D:\Temp\StackOverflow\71345433\volume5
D:\Temp\StackOverflow\71345433\volume1\Extract
D:\Temp\StackOverflow\71345433\volume1\SomeZipFile.zip
D:\Temp\StackOverflow\71345433\volume1\Extract\lat_e_reimage_guide_en-us.pdf
D:\Temp\StackOverflow\71345433\volume2\Extract
D:\Temp\StackOverflow\71345433\volume2\JustAnotherZip.zip
D:\Temp\StackOverflow\71345433\volume2\Extract\latitude-e5440-laptop_owners-manual_en-us.pdf
D:\Temp\StackOverflow\71345433\volume3\Extract
D:\Temp\StackOverflow\71345433\volume3\YetAnotherZip.zip
D:\Temp\StackOverflow\71345433\volume3\Extract\latitude-e5440-laptop_user's guide_en-us.pdf
D:\Temp\StackOverflow\71345433\volume4\Extract
D:\Temp\StackOverflow\71345433\volume4\How Many Zips Was This.zip
D:\Temp\StackOverflow\71345433\volume4\Extract\latitude-e5440-laptop_users-guide_en-us.pdf
D:\Temp\StackOverflow\71345433\volume5\Extract
D:\Temp\StackOverflow\71345433\volume5\Last Zip file.zip
D:\Temp\StackOverflow\71345433\volume5\Extract\latitude-e5440-laptop_white papers_en-us.pdf
For stage 4 we echo both the extract command and xcopy command to see what they look like:
ECHO;"%ProgramFiles%\7-Zip\7z.exe" e -o"%ExtractFolder%" "%%~C"
ECHO; XCOPY /V /C /Y "%ExtractFolder%\*.*" "%CmdPath%\%SubFolderName%.*"
Just a reminder, every test is done by dragging the 5 folders onto the batch file:
"C:\Program Files\7-Zip\7z.exe" e -o"D:\Temp\StackOverflow\71345433\volume5\Extract" "D:\Temp\StackOverflow\71345433\volume5\Last Zip file.zip"
XCOPY /V /C /Y "D:\Temp\StackOverflow\71345433\volume5\Extract\*.*" "D:\Temp\StackOverflow\71345433\\volume5.*"
"C:\Program Files\7-Zip\7z.exe" e -o"D:\Temp\StackOverflow\71345433\volume1\Extract" "D:\Temp\StackOverflow\71345433\volume1\SomeZipFile.zip"
XCOPY /V /C /Y "D:\Temp\StackOverflow\71345433\volume1\Extract\*.*" "D:\Temp\StackOverflow\71345433\\volume1.*"
"C:\Program Files\7-Zip\7z.exe" e -o"D:\Temp\StackOverflow\71345433\volume2\Extract" "D:\Temp\StackOverflow\71345433\volume2\JustAnotherZip.zip"
XCOPY /V /C /Y "D:\Temp\StackOverflow\71345433\volume2\Extract\*.*" "D:\Temp\StackOverflow\71345433\\volume2.*"
"C:\Program Files\7-Zip\7z.exe" e -o"D:\Temp\StackOverflow\71345433\volume3\Extract" "D:\Temp\StackOverflow\71345433\volume3\YetAnotherZip.zip"
XCOPY /V /C /Y "D:\Temp\StackOverflow\71345433\volume3\Extract\*.*" "D:\Temp\StackOverflow\71345433\\volume3.*"
"C:\Program Files\7-Zip\7z.exe" e -o"D:\Temp\StackOverflow\71345433\volume4\Extract" "D:\Temp\StackOverflow\71345433\volume4\How Many Zips Was This.zip"
XCOPY /V /C /Y "D:\Temp\StackOverflow\71345433\volume4\Extract\*.*" "D:\Temp\StackOverflow\71345433\\volume4.*"
Stage 5, try it live:
"%ProgramFiles%\7-Zip\7z.exe" e -o"%ExtractFolder%" "%%~C"
XCOPY /V /C /Y "%ExtractFolder%\*.*" "%CmdPath%\%SubFolderName%.*"
What did we get?:
D:\Temp\StackOverflow\71345433>dir /s/b
D:\Temp\StackOverflow\71345433\volume1
D:\Temp\StackOverflow\71345433\volume1.pdf
D:\Temp\StackOverflow\71345433\volume2
D:\Temp\StackOverflow\71345433\volume2.pdf
D:\Temp\StackOverflow\71345433\volume3
D:\Temp\StackOverflow\71345433\volume3.pdf
D:\Temp\StackOverflow\71345433\volume4
D:\Temp\StackOverflow\71345433\volume4.pdf
D:\Temp\StackOverflow\71345433\volume5
D:\Temp\StackOverflow\71345433\volume5.pdf
Stage 6, what will remove directory look like? (Decided to hide the other commands with REM)
REM "%ProgramFiles%\7-Zip\7z.exe" e -o"%ExtractFolder%" "%%~C"
REM XCOPY /V /C /Y "%ExtractFolder%\*.*" "%CmdPath%\%SubFolderName%.*"
ECHO;RD /Q /S "%Folder%"
And we have:
RD /Q /S "D:\Temp\StackOverflow\71345433\volume5"
RD /Q /S "D:\Temp\StackOverflow\71345433\volume1"
RD /Q /S "D:\Temp\StackOverflow\71345433\volume2"
RD /Q /S "D:\Temp\StackOverflow\71345433\volume3"
RD /Q /S "D:\Temp\StackOverflow\71345433\volume4"
Stage 7 is the final code and tests:
@ECHO OFF
GOTO :Start
:LoopThroughParameters
SET CmdPath=%~1
SHIFT
:ltpLoop
IF [%1] EQU [] GOTO :EOF
SET Folder=%~1
SET SubFolderName=%~nx1
SET ExtractFolder=%~1\Extract
FOR %%C IN ("%Folder%\*.zip" "%Folder%\*.rar") DO (
"%ProgramFiles%\7-Zip\7z.exe" e -o"%ExtractFolder%" "%%~C"
XCOPY /V /C /Y "%ExtractFolder%\*.*" "%CmdPath%\%SubFolderName%.*"
RD /Q /S "%Folder%"
)
SHIFT
GOTO :ltpLoop
:Start
CALL :LoopThroughParameters "%~dp0" %*
PAUSE
All folders were deleted when done.
Now, let's do something experimental. I've never seen this fail, but I haven't used it that often. Let's give it a try:
@ECHO OFF
GOTO :Start
:LoopThroughParameters
SET CmdPath=%~1
SHIFT
:ltpLoop
IF [%1] EQU [] GOTO :EOF
SET Folder=%~1
SET SubFolderName=%~nx1
SET ExtractFolder=%~1\Extract
FOR %%C IN ("%Folder%\*.zip" "%Folder%\*.rar") DO (
(
"%ProgramFiles%\7-Zip\7z.exe" e -o"%ExtractFolder%" "%%~C"
) && (
XCOPY /V /C /Y "%ExtractFolder%\*.*" "%CmdPath%\%SubFolderName%.*"
) && (
RD /Q /S "%Folder%"
) || (
PowerShell Write-Host -ForegroundColor red "Error:"
PAUSE
)
)
SHIFT
GOTO :ltpLoop
:Start
CALL :LoopThroughParameters "%~dp0" %*
If any of the commands separated by && fail, then execution jumps to the command prefixed by ||. But if all of the commands separated by && succeed without throwing an error code, then the command prefixed by || is skipped. In theory, this will prevent the folder from being deleted, and pause the code, if there is problem.
So, we re-created the folders, and then used HxD to the damage zip file in volume4 folder.
It worked perfectly! Folder volume4 was not deleted. Tried the test again, this time damaging the PDF in folder volume2, worked perfectly!
As you can tell, I can do things in Batch that many can't do in PowerShell, and yes @Olaf, that's not necessarily something to be proud of! ;)