Batch script to clean up storage space

2019-09-14 06:45发布

I have a folder structure like below:

  • D:\folder
    • test1
      • opt
        • test1.zip (10 MB)
      • test1.zip (100 MB)
    • test2
      • opt
        • test2.zip (10 MB)
      • test2.zip (100 MB)
    • test3
      • opt
        • test3.zip (10 MB)
      • test3.zip (100 MB)

Same files in a flat list:

D:\folder\test1\test1.zip
D:\folder\test1\opt\test1.zip
D:\folder\test2\test2.zip
D:\folder\test2\opt\test2.zip
D:\folder\test3\test3.zip
D:\folder\test3\opt\test3.zip

I have a script that optimizes zip files. What I need to do in a batch file is to basically find these optimized files in opt folders and overwrite the larger version with the smaller one.

1条回答
We Are One
2楼-- · 2019-09-14 07:05

Take a look on this commented batch code:

@echo off
for /D %%I in ("D:\folder\*") do (
    if exist "%%I\%%~nxI.zip" (
        if exist "%%I\opt\%%~nxI.zip" (
            call :CompareFiles "%%I\%%~nxI.zip" "%%I\opt\%%~nxI.zip"
        )
    )
)
goto :EOF

rem The loop runs on each subdirectory of directory D:\folder. It first
rem checks if there is a *.zip file in the subdirectory with same name as
rem the subdirectory. Next it checks if in the current subdirectory there
rem is a subdirectory with name "opt" with having also a *.zip file with
rem same name as the subdirectory. If this second condition is also true,
rem the subroutine CompareFiles is called with the names of the 2 ZIP files.

rem The subroutine compares the file size of the two ZIP files.
rem The optimized ZIP file is moved over the ZIP file in directory
rem above if being smaller than the ZIP file in directory above.
rem Otherwise the optimized ZIP file being equal or greater as the
rem ZIP file above is deleted.
rem Finally the subdirectory "opt" is deleted which works only if the
rem subdirectory is empty. The error message output by command RD in
rem case of "opt" is not empty is redirected from STDERR to device NUL
rem to suppress it.

rem goto :EOF above results in exiting processing this batch file after
rem finishing the loop and avoids a fall through to the subroutine. The
rem goto :EOF below would not be really necessary as it is at end of the
rem batch file. But it is recommended to end each subroutine with goto :EOF
rem or alternatively exit /B in case of one more subroutine is added later.

:CompareFiles
if %~z1 GTR %~z2 (
    move /Y %2 %1
) else (
    del /F %2
)
rd "%~dp2" 2>nul
goto :EOF

You can test the batch file by inserting command echo left to the commands move and del and run the batch file from within a command prompt window to see the output. When the result is as expected, run the batch file once again without the two added echo.

ATTENTION:

Windows command processor supports only signed 32-bit integer numbers. So this batch code does not work for ZIP files with 2 GiB (= 2.147.483.650 bytes) or more.

%%~nxI references usually file name and file extension. Windows command processor interprets everything after last backslash as name of a file or directory. Here the string assigned to loop variable I is the name of the subdirectory with drive and path D:\folder\ not ending with a backslash. For that reason %%~nI references the name of the current subdirectory in D:\folder\. The file extension is defined as everything after last point. Directories usually don't have a point in directory name and so %%~nI is often also enough for a directory name. But it is possible to create directories also with a point in directory name. Therefore using %%~nxI is more safe as working for any directory name.

Note: Subdirectories with hidden or system attribute are ignored by command FOR.

It is 100% safe to use just %1 and %2 in subroutine CompareFiles instead of "%~1" and "%~2" as both file names must be passed already enclosed in double quotes to the subroutine on containing a space or one of these characters: &()[]{}^=;!'+,`~. So it does not make sense from an execution point of view to specify on move and del the arguments (file names) with "%~1" and "%~2". But it is of course possible to use "%~1" and "%~2" for example for better syntax highlighting in text editor or for uniformed file name references passed as arguments to a batch file or subroutine.

The batch file can be simplified on not testing if the two ZIP files exist at all and the optimized ZIP file is really smaller.

@echo off
for /D %%I in ("D:\folder\*") do (
    move /Y "%%I\opt\%%~nxI.zip" "%%I\%%~nxI.zip" 2>nul
    rd "%%I\opt" 2>nul
)

The error message output in case of optimized ZIP file not existing is suppressed by redirecting it to device NUL.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • call /?
  • del /?
  • echo /?
  • for /?
  • goto /?
  • if /?
  • move /?
  • rd /?

See also the Microsoft article Using command redirection operators for details on 2>nul.

查看更多
登录 后发表回答