1
\$\begingroup\$

Recently, I've been doing more and more Batch "programming".

I always find myself in the need to extract a file and do something with the files.
This is not my first version, and a few non-general-purpose were written.

However, I've re-written it all to be general-purpose.

:extractfile
REM extracts the file with whichever program is available
REM %1 = file to extract, %2 = optional target for extraction, %3 = log file path
REM exit: 0 = extracted, 1 = not found, 2 = failed, 3 = no program
set "extractfile="
setlocal EnableDelayedExpansion
set "folder=%~dp1"
set "file=%~nx1"
set "filename=%~n1"

IF NOT EXIST "!folder!!file!" (
    exit /b 1
)

set "target=%~dp2"
IF "!target!" EQU "" (
    SET "target=!folder!!filename!\"
)

REM set "LOG=%~dpnx3"
REM https://codereview.stackexchange.com/questions/208756/function-to-extract-a-file-in-batch#comment405176_208756
IF "%~3" EQU "" (
    set "LOG=nul"
) else (
    set "LOG="%~dpnx3""
)

set "CMD="

echo === COMPRESSED FILE EXTRACTION === >> !LOG!

REM yeah, not pretty, but the %ProgramFiles(x86)% causes syntax errors
FOR %%d IN ("%ProgramFiles%" "%ProgramFiles(x86)%") DO IF "!CMD!" EQU "" (
    set "DIR=%%d"
    IF "!DIR!" NEQ "" (
        set "DIR=!DIR:"=!"
        IF EXIST "!DIR!\7-Zip\7z.exe" (
            REM https://stackoverflow.com/q/14122732
            set "CMD="!DIR!\7-Zip\7z.exe" x "!folder!!file!" -bd -y -o"!target!\""
        ) ELSE IF EXIST "!DIR!\WinRAR\winrar.exe" (
            REM https://stackoverflow.com/a/19337595
            set "CMD="!DIR!\WinRAR\winrar.exe" x -ibck "!folder!!file!" *.* "!target!\""
        ) ELSE IF EXIST "!DIR!\winzip\wzzip.exe" (
            REM http://kb.winzip.com/kb/entry/125/ - WZCLINE.CHM
            set "CMD="!DIR!\winzip\wzzip.exe" -d "!folder!!file!" "!target!\""
        )
    )
)

IF "!CMD!" EQU "" (
    echo Error 3: Extraction failed, no program found >> !LOG!
    echo === COMPRESSED FILE EXTRACTION FINISHED === >> !LOG!

    exit /b 3
)

echo Extracting using command: >> !LOG!
echo !CMD! >> !LOG!
call !CMD! >> !LOG! 2>&1

IF ERRORLEVEL 1 (
    echo Error 2: Extraction failed with error %ERRORLEVEL% >> !LOG!
    echo === COMPRESSED FILE EXTRACTION FINISHED === >> !LOG!

    exit /b 2
)

echo === COMPRESSED FILE EXTRACTION FINISHED === >> !LOG!

endlocal & set "extractfile=!target!\"
goto :eof

This function uses the available program to extract the file and "returns" the path to the folder.

Assuming the following basic example:

call :extractfile a.zip abc
echo %extractfile%

This should output something like c:\[...]\abc on success.
Also responds with the following error codes:

  • 0: extraction succeeded
  • 1: file not found
  • 2: extraction failed
  • 3: couldnt find a suitable program to extract

If the 2nd argument isn't passed, it is supposed to create a sub-folder with everything inside.

(You can see this in action in https://github.com/ismael-miguel/bnsbuddy_mod_installer/blob/master/mod_installer.bat)

I've tried to keep it as DRY as possible, and as short as I could.

Is there anything I've missed or that I should improve?

\$\endgroup\$
  • 1
    \$\begingroup\$ /OT - This looks like magic to me - have you ever considered using PowerShell? I admire you for working with batch scripts ;-) \$\endgroup\$ – t3chb0t Nov 30 '18 at 11:52
  • \$\begingroup\$ I have considered, but this that I'm writting is to go to a variety of systems, which have a variety of PowerShell versions with a variety of functionalities. I definetivelly should try learning PowerShell, but my interest has been a bit low on it. And for what I'm doing, Batch works just fi... okay-ish... \$\endgroup\$ – Ismael Miguel Nov 30 '18 at 11:59
  • \$\begingroup\$ 1st: if supplied %2 then %~dp2 already contains trailing backslash; hence, use set "target=%~dp2" and then IF "!target!"=="" (. 2nd ad mod_installer.bat (above this topic): define if "%~3"=="" (set "LOG=nul") else set "LOG=%~dpnx3"; then you could save all next IF "!LOG!" NEQ "" ( tests just using >>"!LOG!" \$\endgroup\$ – JosefZ Dec 13 '18 at 18:40
  • \$\begingroup\$ @JosefZ Thank you for the tips. I've been having some syntax issues with some edits I was doing and only fixed them today. The version that was present here was fully functional, but isn't the latest in the github. As such, I've ninja-edited the latest version. \$\endgroup\$ – Ismael Miguel Dec 31 '18 at 17:14

Your Answer

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

Browse other questions tagged or ask your own question.