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.
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.
Related
I have a folder full of zip files. Those zip files sometimes contain zip files, that sometimes contain zip files within them, and so on. I am trying to write a batch file that I can paste into the top folder containing all the zips, and when it runs it will unzip all the nested zip files, and within sub-directories, all the way down, and delete the zips once they have been successfully extracted. The full file paths need to be preserved. If there is an error and a file cannot be extracted then it should not be deleted and the file and file path need to be printed to a text file.
So far I have this:
#ECHO ON
SET source=%cd%
FOR /F "TOKENS=*" %%F IN ('DIR /S /B "%source%\*.zip"') DO "C:\Program Files\7-Zip\7z.exe" x "%%~fF" -o"%%~pF\"
EXIT
Which I can drop into a folder and run, it will unzip the first level of zips but none of the nested zips inside. That's the first hurdle.
The next hurdle would be to delete the successfully extracted zips. And last, not to delete any zips that could not be extracted and print their name and/or path to a text file.
Any suggestions or chunks of code are appreciated. Or if there's a better way to do this entirely.
**** UPDATED ****
Mofi posted an answer that looks like it's working except for one piece:
When a ZIP is extracted, it needs to be extracted to a folder with the same name, so I can still follow the structure.
Starting Example:
[Top Level Folder Holding Zips] (folder)
--ExampleZip.zip
---FileInZip.txt
---FileinZip2.txt
--ExampleZip2.zip
---Folder1 (folder)
----ExampleZip3.zip
-----FileinZip3.txt
-----FileinZip4.txt
---ExampleZip4.zip
----FileinZip5.txt
----FileinZip6.txt
Needs to become this:
[Top Level Folder Holding Zips] (folder)
--ExampleZip (folder)
---FileInZip.txt
---FileinZip2.txt
--ExampleZip2 (folder)
---Folder1 (folder)
----ExampleZip3 (folder)
-----FileinZip3.txt
-----FileinZip4.txt
---ExampleZip4 (folder)
----FileinZip5.txt
----FileinZip6.txt
So the full structure is still visible.
I think the top answer in this question shows what I need to include: Extract zip contents into directory with same name as zip file, retain directory structure
This part:
SET "filename=%~1"
SET dirName=%filename:~0,-4%
7z x -o"%dirName%" "%filename%"
Needs to be smashed in there somewhere. Or it seems like there should be a switch for 7Zip that does it, since you can do this from the context menu with "Extract to *" I thought that's what the "extract with full paths" command does but that must have something to do with the -o switch, specifying output path? How do I specify the output path to be a folder with the same name as the input zip? Or merge the answer from that question I linked with Mofi's answer?
*** UPDATED AGAIN ***
I thought there was an issue with the batch file ignoring ZIP files with underscores in the name, but that was a coincidence and it was actually ignoring ZIP files without the Archive file attribute set.
Mofi suggested another fix for that which worked, but the batch file is not extracting nested zips that needed the Archive file attribute set.
This does kind of work, in that I can manually execute the batch file a few times and it will work it's way through everything in the folder, but the loop calculation does not seem to work, or is calculating/terminating before the batch file sets the Archive attribute for all zip files?
Here is the current version I'm working with:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "ErrorOutput="
set "LoopCount=20"
rem The current directory is used on batch file being called without
rem a base folder path or with just one or more double quotes.
set "BaseFolder=%~1"
if defined BaseFolder set "BaseFolder=%BaseFolder:"=%"
if not defined BaseFolder set "BaseFolder=%CD%" & goto VerifyFolderPath
rem Make sure the folder path contains backslashes and not forward slashes
rem and does not contain wildcard characters or redirection operators or a
rem horizontal tab character after removing all double quotes.
set "BaseFolder=%BaseFolder:/=\%"
for /F "delims=*?|<> " %%I in ("%BaseFolder%") do if not "%BaseFolder%" == "%%I" (
echo ERROR: %~nx0 must be called with a valid folder path.
echo "%~1" is not a valid folder path.
set "ErrorOutput=1"
goto EndBatch
)
rem Get full folder path in case of the folder was specified with
rem a relative path. If the folder path references the root of a
rem drive like on using "C:\" or just "\", redefine the folder
rem path with full path for root of the (current) drive.
for %%I in ("%BaseFolder%") do set "BaseFolder=%%~fI"
:VerifyFolderPath
rem The base folder path must end with a backslash for verification.
if not "%BaseFolder:~-1%" == "\" set "BaseFolder=%BaseFolder%\"
rem Verify the existence of the folder. The code above processed also
rem folder paths of folders not existing at all and also invalid folder
rem paths containing for example a colon not (only) after drive letter.
if not exist "%BaseFolder%" (
echo ERROR: Folder "%BaseFolder%" does not exist.
set "ErrorOutput=1"
goto EndBatch
)
rem Make sure to process all ZIP files existing in base folder and all
rem its subfolders by setting archive file attribute on all ZIP files.
%SystemRoot%\System32\attrib.exe +A /S "%BaseFolder%*.zip"
rem Process all *.zip files found in base folder and all its subfolders
rem which have the archive file attribute set. *.zip files with archive
rem file attribute not set are ignored to avoid an endless running loop
rem if a ZIP archive file cannot be extracted successfully with reason(s)
rem output by 7-Zip or if the ZIP file cannot be deleted after successful
rem extraction of the archive. The archive extraction loop runs are limited
rem additionally by a loop counter as defined at top of the batch file for
rem 100% safety on prevention of an endless loop execution.
:ExtractArchives
set "ArchiveProcessed="
for /F "delims=" %%I in ('dir "%BaseFolder%*.zip" /AA-D /B /S 2^>nul') do (
set "ArchiveProcessed=1"
echo Extracting archive: "%%I"
"%ProgramFiles%\7-Zip\7z.exe" x -bd -bso0 -o"%%~dpnI\" -spd -y -- "%%I"
#pause
if errorlevel 255 set "ErrorOutput=1" & goto EndBatch
if errorlevel 1 (
set "ErrorOutput=1"
%SystemRoot%\System32\attrib.exe -A "%%I"
) else (
del /A /F "%%I"
if exist "%%I" (
echo ERROR: Failed to delete: "%%I"
set "ErrorOutput=1"
%SystemRoot%\System32\attrib.exe -A "%%I"
)
)
)
if not defined ArchiveProcessed goto EndBatch
set /A LoopCount-=1
if not LoopCount == 0 goto ExtractArchives
:EndBatch
if defined ErrorOutput echo/& pause
endlocal
echo[
echo[
echo If no errors are displayed above, everything extracted successfully. Remember to delete the batch file once you are done.
#pause
It is rare that there would be maybe 10 or 20 layers of nested zips, so a quick and dirty fix may be just somehow looping the whole batch file 10 or 20 times, unless that is a bad idea or there is a more elegant way to do it.
The task to recursively extract all ZIP archives including nested ZIP archives inside a ZIP archive can be achieved by running the ZIP archive file extraction process in a loop until no ZIP file exists anymore. But there must be at least two use cases taken into account to avoid an endless running archive extraction loop:
The extraction of a ZIP archive file fails for whatever reason. 7-Zip outputs information about the error reason(s). Such a ZIP file should not be processed a second time.
The deletion of a successfully extracted ZIP file fails for whatever reason. The ZIP file should not be processed once again.
The solution is processing only ZIP files with archive file attribute set as done automatically by Windows on creating, renaming or modifying a file and remove the archive file attribute on every ZIP file on which the extraction process or the deletion of the file failed to avoid processing the ZIP file again.
The archive file attribute is set on all *.zip files on directory tree to process before starting the archive files extraction process to make sure that really all existing *.zip files are processed at least once. The archive file attribute is also set on all *.zip files in output directory of a completely successfully processed ZIP archive file to make sure that even *.zip files inside a ZIP file with archive file attribute not set after extraction are processed also on next archive file extraction loop run.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "ErrorOutput="
set "LoopCount=20"
rem The current directory is used on batch file being called without
rem a base folder path or with just one or more double quotes.
set "BaseFolder=%~1"
if defined BaseFolder set "BaseFolder=%BaseFolder:"=%"
if not defined BaseFolder set "BaseFolder=%CD%" & goto VerifyFolderPath
rem Make sure the folder path contains backslashes and not forward slashes
rem and does not contain wildcard characters or redirection operators or a
rem horizontal tab character after removing all double quotes.
set "BaseFolder=%BaseFolder:/=\%"
for /F "delims=*?|<> " %%I in ("%BaseFolder%") do if not "%BaseFolder%" == "%%I" (
echo ERROR: %~nx0 must be called with a valid folder path.
echo "%~1" is not a valid folder path.
set "ErrorOutput=1"
goto EndBatch
)
rem Get full folder path in case of the folder was specified with
rem a relative path. If the folder path references the root of a
rem drive like on using "C:\" or just "\", redefine the folder
rem path with full path for root of the (current) drive.
for %%I in ("%BaseFolder%") do set "BaseFolder=%%~fI"
:VerifyFolderPath
rem The base folder path must end with a backslash for verification.
if not "%BaseFolder:~-1%" == "\" set "BaseFolder=%BaseFolder%\"
rem Verify the existence of the folder. The code above processed also
rem folder paths of folders not existing at all and also invalid folder
rem paths containing for example a colon not (only) after drive letter.
if not exist "%BaseFolder%" (
echo ERROR: Folder "%BaseFolder%" does not exist.
set "ErrorOutput=1"
goto EndBatch
)
rem Make sure to process all ZIP files existing in base folder and all
rem its subfolders by setting archive file attribute on all ZIP files.
%SystemRoot%\System32\attrib.exe +A /S "%BaseFolder%*.zip" >nul
rem Process all *.zip files found in base folder and all its subfolders
rem which have the archive file attribute set. *.zip files with archive
rem file attribute not set are ignored to avoid an endless running loop
rem if a ZIP archive file cannot be extracted successfully with reason(s)
rem output by 7-Zip or if the ZIP file cannot be deleted after successful
rem extraction of the archive. The archive extraction loop runs are limited
rem additionally by a loop counter as defined at top of the batch file for
rem 100% safety on prevention of an endless loop execution.
:ExtractArchives
set "ArchiveProcessed="
for /F "delims=" %%I in ('dir "%BaseFolder%*.zip" /AA-D /B /S 2^>nul') do (
set "ArchiveProcessed=1"
echo Extracting archive: "%%I"
"%ProgramFiles%\7-Zip\7z.exe" x -bd -bso0 -o"%%~dpI" -spd -y -- "%%I"
if errorlevel 255 set "ErrorOutput=1" & goto EndBatch
if errorlevel 1 (
set "ErrorOutput=1"
%SystemRoot%\System32\attrib.exe -A "%%I"
) else (
%SystemRoot%\System32\attrib.exe +A /S "%%~dpnI\*.zip" >nul
del /A /F "%%I"
if exist "%%I" (
echo ERROR: Failed to delete: "%%I"
set "ErrorOutput=1"
%SystemRoot%\System32\attrib.exe -A "%%I"
)
)
)
if not defined ArchiveProcessed goto EndBatch
set /A LoopCount-=1
if not LoopCount == 0 goto ExtractArchives
:EndBatch
if defined ErrorOutput echo/& pause
endlocal
Note: There must be one horizontal tab character after "delims=*?|<> and " on line 16 of the batch file code and not a series of space characters as there will be after copying the code from browser window and pasting the code into a text editor window.
The batch file is commented with lines with command REM (remark). These comments should be read for understanding the code and then can be removed for a more efficient execution of the batch file by Windows command processor.
The 7-Zip switches used in code are explained by help of 7-Zip opened by double clicking on file 7-zip.chm or opening Help from within GUI window of started 7-Zip. On help tab Contents expand the list item Command Line Version and click on list item Switches to get displayed the help page Command Line Switches with all switches supported by currently used version of 7-Zip.
The batch file can be executed with a folder path as argument to process all ZIP files in this folder and all its subfolders. So it is possible to add to Send to context menu of Windows File Explorer a shortcut file which runs the batch file with the folder path passed by Windows File Explorer to the batch file as first argument. It would be also possible to registry the batch file as context menu option for Directory in Windows registry to be able to run the batch file easily from within any application supporting the Windows context menu handlers for a directory.
Edit after question edited: The command line running 7-Zip can be modified to:
"%ProgramFiles%\7-Zip\7z.exe" x -bd -bso0 -o"%%~dpnI\" -spe -spd -y -- "%%I"
Each ZIP file is extracted with this command line into a subfolder in folder of the ZIP file with name of the ZIP file because of replacing -o"%%~dpI" by -o"%%~dpnI\". The additional 7-Zip switch -spe avoids duplicating the folder name if the ZIP file contains at top level a folder with same name as the ZIP file. So if Example3.zip contains at top level the folder Example3, the files are extracted to folder Example3 and not to folder Example3\Example3 as it would occur without usage of option -spe.
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.
attrib /?
call /?
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
rem /?
set /?
setlocal /?
Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background.
Using Groovy, or Ant
This would be a lot easier using Apache Ant or, better still, the Groovy AntBuilder.
e.g. this Groovy script will unzip all the top leval zip files then delete them:
new AntBuilder().with {
def sourceRoot = '.'
// Unzip all .zip files in / underneath sourceRoot
unzip( dest: 'some-folder' ) {
fileset( dir: sourceRoot ) {
include name: "**/*.zip"
}
}
// Unzip throws an exception on failure.
// Delete all .zip files in / underneath sourceRoot
delete {
fileset( dir: sourceRoot, includes: '**/*.zip' )
}
}
You'll need to keep scanning the destination folder for zips, and repeating the above process, until everythings unzipped. You may also find it useful to use a FileScanner.
AntBuilder throws an exception if anything fails, so you can avoid deleting archives that fail to unzip. AntBuilder will also log it's progress, using the standard Java logging mechanisms. You can tell it the level of detail you want, or supress it completely
The full AntBuilder documentation is here:
http://docs.groovy-lang.org/latest/html/documentation/ant-builder.html
Using a fileScanner
Example from the Groovy AntBuilder documentation:
// let's create a scanner of filesets
def scanner = ant.fileScanner {
fileset(dir:"src/test") {
include(name:"**/My*.groovy")
}
}
// now let's iterate over
def found = false
for (f in scanner) {
println("Found file $f")
found = true
assert f instanceof File
assert f.name.endsWith(".groovy")
}
assert found
Putting it together
It's not a huge leap to combine a filesScanner with an AntBuilder to get the job done. I suspect it will be a lot easier than doing it with a batch script.
Finally managed to write a batch file that can unzip nested zips, keeping the archive file structure intact!
logic is that, run recursively until all the zip files are unzipped. Number of iterations default is 5, and can be passed as cmd arg "extract.bat 3". may be changed to a while loop until hit file not found exception. And most importantly delete the archive file after extraction, so, we don't get into endless loop!
But follow the rules below
it uses 7z, make sure in the cmd window 7z can be run, that is in the path
zip file names cannot have spaces. make sure of that and ext is zip
copy the zip file to a directory where there are no other zip files
And only .zip ext, you may change that to rar or anything in the batch file
Here is the batch file
Rem Nested unzip - #sivakd
echo off
if "%1"=="" (set iter=5) else (set iter=%1)
echo Running %iter% iterations
for /l %%x in (1, 1, %iter%) do (
dir *.zip /s /b > ziplist.txt
for /F %%f in (ziplist.txt) do (
7z x %%f -o%%~dpnf -y & del /f %%f
)
del ziplist.txt
)
Been trying to create an additional batch script that processes files for me. I either get send 1 or several .pdf test files in a .rar file.
So what I am trying to aim for is:
If the first variable 1 is named 'test' then
Is there a .rar file in the folder from variable 2 then
Extract to a folder and then delete .rar file
else
check that there is a .pdf file and then copy to folder
Else
Tell the user that neither a file or a archive has been found
I've managed to scrape this together but I need help trying to expand it further to include all the options:
#echo off
set "cat=%1"
IF "%cat%"=="test" ( for /f %%G in ('dir *.rar /b') do set filename=%%~G)
echo %filename%
This only gives me half the file name as they have gaps in the filename, also need to change the dir in the 3rd line to be looking in variable 2 that is sent in.
To add to it I've just been told that it's the same for .txt files, the multiples are sent to me in a .rar file
I suggest to open a command prompt, run call /? and read the output help. The help explains how the arguments – also called options or parameters, but not variables – of a batch file can be referenced from within a batch file.
It is advisable to check if a batch file is called with at least one argument if it must be called with at least one argument and output a help for correct usage of the batch file if it was started without any argument or if it was started with /? which is the default on Windows to get help about a command or program.
The manual for console version of WinRAR is the file Rar.txt in program files folder of WinRAR. It can be read in this text file after opening it with a double click that Rar.exe can extract one or more *.rar archive files found in a directory. For that reason it is not really necessary to use command FOR. But it is advisable for this task to use command FOR as the RAR file(s) should be deleted after successful extraction of the RAR archive(s).
Let us look on the FOR command line for /f %%G in ('dir *.rar /b') do and what it does on execution.
FOR with option /F to process a text file content or a single string or the output of a command line results in this case in starting a command process in background with %ComSpec% /c and the command line between the two ' appended. So executed by the Windows command process cmd.exe processing the batch file with for /F is the following with Windows installed into C:\Windows as by default:
C:\Windows\System32\cmd.exe /c dir *.rar /b
The command DIR executed by separate command process in background
searches in current directory
for directory entries (files or directories)
matching the wildcard pattern *.rar
and not having hidden attribute set (implicit default is /A-H on option /A not specified at all)
and outputs to handle STDOUT the found directory entries matching the criteria above in bare format line by line which means with just file/folder name without path and never enclosed in double quotes even on containing a space or one of these characters &()[]{}^=;!'+,`~.
An error message is output by DIR to handle STDERR of background command process if it cannot find any directory entry matching the search criteria.
FOR respectively the command process processing the batch file redirects the output to handle STDERR of the background command process to its own STDERR handle which results in getting it displayed in console window in this case. But the output to handle STDOUT of started background command process is captured by FOR respectively the command process processing the batch file and is processed line by line after started background command process terminated itself.
FOR used with option /F always ignores empty lines. This does not matter here because of DIR does not output empty lines on being executed with option /B.
for /F splits up a non-empty line by default into substrings using normal space and horizontal tab as string delimiters and assigns by default just first space/tab separated string to the specified loop variable which is here the loop variable G. for /F ignores by default additionally also a processed line if the first substring after splitting the line up starts with a semicolon because of eol=; is the default for end of line option.
So the command line for /f %%G in ('dir *.rar /b') do causes several problems on processing the list of directory entries output by DIR.
For a file/folder name containing a space just the first space/tab separated part of the file/folder name is assigned to loop variable G instead of complete name. For example a name like My Archive.rar results in just My is assigned to the loop variable G.
A file/folder name with one or more leading spaces is assigned to loop variable G without those leading spaces which means again that G does not hold complete name. For example a name like TwoLeadingSpaces.rar results in getting assigned to loop variable G just TwoLeadingSpaces.rar without the two leading spaces and the file (or folder) is not found on referencing the value of loop variable G.
A file/folder name with a semicolon at beginning after zero or more leading spaces is completely ignored by command FOR for further processing. For example names like ;Test.rar (name beginning with a semicolon) or ;TestWithALeadingSpace.rar (name with leading space and a semicolon) are completely ignored for further processing by FOR.
The points 2 and 3 are usually no problem as file/folder names with leading space(s) or a semicolon at beginning are really very rare. But a file/folder name with a space occurs very often.
A solution would be using FOR without option /F:
for %%G in (*.rar) do
FOR searches now itself for non-hidden files (not directories) in the current directory matching the wildcard pattern *.rar and assigns a found file name without path to loop variable G and next runs the command(s) after do. There is no additional command process started and there is no substring splitting done.
But there is a problem with this very simple solution in case of the commands executed for each found file name delete, move or rename files matched by the wildcard pattern *.rar. The list of directory entries matching the wildcard pattern changes on each iteration of the body of the FOR loop while command FOR queries the directory entries one after the other with executing the commands between each directory query. This is especially on FAT16, FAT32 and exFAT drives a real problem, but can result also in unexpected behavior on NTFS drives.
Whenever a FOR loop is used to process a list of files which could change during the iterations of the loop because of deleting, moving or renaming the files matched by a wildcard pattern, it is better to process a list of files loaded completely into memory before first iteration of the loop.
So a better solution for this task with the requirement to delete a RAR archive file after successful extraction is:
for /F "eol=| delims=" %%I in ('dir *.rar /A-D /B 2^>nul') do
The DIR option /A-D results in ignoring directory entries with attribute directory. So output by DIR are just file names matching the wildcard pattern in current directory including hidden RAR archive files.
2^>nul is passed as 2>nul to the background command process which results in redirecting the error message output by DIR on no *.rar file found to device NUL to suppress it.
Read the Microsoft article about Using command redirection operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background.
The for /F option eol=| changes the end of line character from ; to |. No file name can have a vertical bar in its file name according to Microsoft documentation about Naming Files, Paths, and Namespaces. So no file name is ignored anymore by FOR because of end of file option.
The for /F option delims= changes the delimiters list for line splitting into substrings to an empty list of delimiters which disables the line splitting behavior completely. So a file name with one or more spaces anywhere in file name is assigned completely to the specified loop variable I.
The task description is not very clear regarding to what to do depending on the batch file arguments, especially if the first argument is not case-insensitive test.
However, the following commented batch file could be working for this task on being called with first argument being test or with no arguments at all or with /? as first argument.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
if "%~1" == "" goto OutputHelp
if "%~1" == "/?" goto OutputHelp
if /I not "%~1" == "test" goto MoreCode
set "SourceFolder=%~2"
if defined SourceFolder goto CheckFolder
echo/
echo Error: Folder with RAR or PDF file(s) not specified on command line.
goto OutputHelp
:CheckFolder
rem Replace all forward slashes by backslashes in folder name.
set "SourceFolder=%SourceFolder:/=\%"
rem Append a backslash to folder path if it does not end with a backslash.
if not "%SourceFolder:~-1%" == "\" set "SourceFolder=%SourceFolder%\"
rem Check the existence of the source folder.
if exist "%SourceFolder%" goto ProcessFolder
echo/
echo Error: Folder "%SourceFolder%" does not exist.
goto OutputHelp
:ProcessFolder
rem Get full qualidfied folder name, i.e. the folder name
rem with its absolute path and ending with a backslash.
for %%I in ("%SourceFolder%") do set "SourceFolder=%%~fI"
rem Define the destination folder for the PDF files extracted from the
rem RAR archive file(s) in source folder or copied from source folder.
set "DestinationFolder=C:\Temp\Test\"
rem Search for all *.rar files in folder passed with second argument and
rem extract all *.pdf files in each RAR archive file to the configured
rem destination folder. Rar.exe creates the destination folder automatically
rem if it is not already existing. The batch file is halted after processing
rem a RAR file on which Rar.exe exited with a value greater 0. Read the exit
rem codes documentation of Rar.exe at bottom of text file Rar.txt for more
rem information about the RAR exit codes. See Rar.txt also for the meaning
rem of the few RAR switches used here.
set "RarFileCount=0"
for /F "eol=| delims=" %%I in ('dir "%SourceFolder%*.rar" /A-D /B 2^>nul') do (
set /A RarFileCount+=1
"%ProgramFiles%\WinRAR\Rar.exe" e -cfg- -idcdp -or -- "%SourceFolder%%%I" *.pdf "%DestinationFolder%"
if not errorlevel 1 (del /A /F "%SourceFolder%%%I") else echo/& pause
)
if %RarFileCount% == 0 goto CheckFiles
if %RarFileCount% == 1 (set "PluralS=") else set "PluralS=s"
echo/
echo Info: Processed %RarFileCount% *.rar file%PluralS% in folder "%SourceFolder%".
goto EndBatch
:CheckFiles
echo Info: There are no *.rar files in folder "%SourceFolder%".
if exist "%SourceFolder%*.pdf" goto CopyFiles
echo Info: There are no *.pdf files in folder "%SourceFolder%".
goto EndBatch
:CopyFiles
rem Copy all PDF files in source folder to destination folder. xcopy.exe
rem creates destination folder automatically if it is not already existing.
echo/
%SystemRoot%\System32\xcopy.exe "%SourceFolder%*.pdf" "%DestinationFolder%" /C /I /Y
goto EndBatch
:OutputHelp
echo/
echo Usage: %~n0 [TEST] [Folder with RAR or PDF file(s)]
echo/
echo If the first argument is case-insensitive TEST, the second argument
echo specifies the folder containing the RAR files to extract or the PDF
echo files to copy to destination folder. The folder must be specified
echo with first argument being TEST.
echo/
pause
goto EndBatch
:MoreCode
rem Add here the code to execute on first argument is not case-insensitive TEST.
:EndBatch
endlocal
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 /?
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
rem /?
set /?
setlocal /?
xcopy /?
"%ProgramFiles%\WinRAR\Rar.exe" /?
You can use this:
#echo off
set "cat=%~1"
IF "%cat%"=="test" (
for %%G in (*.rar) do set filename=%%G
)
echo %filename%
Here wildcard is used to get all the rar files in the directory.
I have videos files with filenames:
Series.Name.S01E01.andalotofstuff.mkv
Series.Name.S01E02.andalotofstuff.mkv
Series.Name.S02E01.andalotofstuff.mkv
etc.
where andalotofstuff is not necessarily the same in each file, and can include ., - and [].
I also have subtitles files with filenames:
Series Name 1x01 - Episode Name andotherstuff.srt
Series Name 1x02 - Episode Name andotherstuff.srt
Series Name 2x01 - Episode Name andotherstuff.srt
etc.
where andotherstuff is not necessarily the same in each file, and can include ().
What i want is to rename srt files with the corresponding mkv filename with a batch script, if possible, and i have no idea how.
Some real examples are:
Marvels.Agents.of.S.H.I.E.L.D.S05E04.720p.HDTV.x264-AVS[eztv].mkv
Marvel's Agents of S.H.I.E.L.D. 5x04 - A Life Earned (Español (Latinoamérica)).srt
The.Shannara.Chronicles.S02E08.720p.HDTV.x264-AVS[eztv].mkv
The Shannara Chronicles 2x08 - Amberle (Español (España)).srt
The.Shannara.Chronicles.S02E10.720p.HDTV.x264-KILLERS[eztv].mkv
The Shannara Chronicles 2x10 - Blood (English).srt
Note that not necessarily all video files has a corresponding subtitle file.
Here i found something that is supposed to work on linux...
Here is a commented batch file for this task:
#echo off
rem Setup a local environment for this batch file creating lots
rem of environment variables which should not exist anymore after
rem finishing batch file execution.
setlocal EnableExtensions DisableDelayedExpansion
rem Get all *.mkv and *.srt file names in current directory without path
rem and without file extension loaded into memory assigned to environment
rem variables with name mkv_1, mkv_2, ..., srt_1, srt_2, ... using the
rem two subroutines GetFileList and AddFileToList.
call :GetFileList mkv
call :GetFileList srt
goto ValidateFileCounts
rem Subroutine GetFileList runs command FOR which executes command DIR in
rem a separate command process in background which outputs all file names
rem with the file extension passed to the subroutine as first parameter
rem sorted by name. Each file name output by DIR is assigned to an environment
rem variable with passed file extension, an underscore and an incremented
rem number as variable name. The number of files with given file extension
rem is assigned to an environment variable with name FileCount_Extension.
:GetFileList
set "FileNumber=0"
set "FileExtension=%1"
for /F "delims=" %%I in ('dir *.%FileExtension% /A-D /B /ON 2^>nul') do call :AddFileToList "%%~nI"
set "FileCount_%FileExtension%=%FileNumber%"
goto :EOF
rem Subroutine AddFileToList increments current file number by one and then
rem assigns the file name without file extension and without path passed
rem from calling subroutine GetFileList as first and only parameter to
rem an environment variable with automatically generated varible name.
:AddFileToList
set /A FileNumber+=1
set "%FileExtension%_%FileNumber%=%~1"
goto :EOF
rem After creating the two file lists in memory it is validated that the
rem file rename operation can be started at all. There must be *.srt files
rem found in current directory and the number of *.mkv files must be equal
rem the number of *.srt files.
:ValidateFileCounts
if %FileCount_srt% == 0 (
echo/
echo There are no *.srt files in directory:
echo/
echo %CD%
echo/
pause
goto EndBatch
)
if not %FileCount_mkv% == %FileCount_srt% (
echo/
echo Number of *.mkv files is not equal number of *.srt files in directory:
echo/
echo %CD%
echo/
pause
goto EndBatch
)
rem Now delayed environment variable expansion is needed for the file rename
rem operation in a loop which could not be enabled at beginning of the batch
rem file in case of any file name contains one or more exclamation marks.
rem *.srt files having already the same file name as corresponding *.mkv
rem file detected by identical current and new file name are ignored for
rem the rename operation.
rem It is also not possible to rename a *.srt file to name of a *.srt which
rem already exists. In this case an error message is output for the *.srt
rem file which cannot be renamed and finally PAUSE is executed to give the
rem batch file user the possibility to read all those file rename errors.
rem But it is very unlikely that this error message is displayed ever.
setlocal EnableDelayedExpansion
set "RenameError="
for /L %%I in (1,1,%FileCount_srt%) do (
set "FileNameNew=!mkv_%%I!.srt"
set "FileNameNow=!srt_%%I!.srt"
if not "!FileNameNew!" == "!FileNameNow!" (
if not exist "!FileNameNew!" (
ren "!FileNameNow!" "!FileNameNew!"
) else (
echo Rename file !FileNameNow!
echo to new name !FileNameNew!
echo not possible as such a file exists already.
echo/
set "RenameError=1"
)
)
)
if defined RenameError pause
endlocal
rem The previous environment is restored finally which means all environment
rem variables created by this batch file are removed from memory. There is
rem neither a message output nor batch file processing halted if no error
rem occurred during entire process.
:EndBatch
endlocal
There is no real file name matching algorithm used as it looks like the algorithm is human language intelligence. So the batch file just loads into memory the list of *.mkv file names sorted by name and the list of *.srt file names also sorted by name and then renames first *.srt file to name of first *.mkv file, second *.srt file to name of second *.mkv file, and so on. This simple solution worked for the given examples.
It is possible to insert the command echo left to command ren and append command pause at end of the batch file or run it from within a command prompt window to see all the file rename operations without really doing them for verification by user before really renaming the *.srt files.
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 /?
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
rem /?
ren /?
setlocal /?
Read also the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background.
Read this answer for details about the commands SETLOCAL and ENDLOCAL and Where does GOTO :EOF return to?
In Windows you can do it with program called "Subtitle And Video Renamer". I just tested version 0.5.1 and I renamed ~30 subtitles with 2 buttons click.
My question is related to: Batch Rename contents of ZIP file to ZIP file name
But I am looking for a simpler batch file, as I do not understand that very well.
I have about 600 .7z files. I want these 7z files names to match a .cue file contained in each of the .7z file.
To make it more clear, I give an example below:
File Crash Bandicot PSX 1995.7z contains:
Crash Bandicot (USA) track 1.bin
Crash Bandicot (USA) track 2.bin
Crash Bandicot (USA) track 3.bin
Crash Bandicot (USA).cue
I would like to rename the .7z name to match the .cue file (preferably). Like this:
Crash Bandicot (USA).7z still containing:
Crash Bandicot (USA) track 1.bin
Crash Bandicot (USA) track 2.bin
Crash Bandicot (USA) track 3.bin
Crash Bandicot (USA).cue
Could someone help me out to make a batch to do this?
Edit:This is the script code I have so far:
FOR /r %%i IN (*) DO "C:\Program Files (x86)\7-Zip\7z.exe" a "%%~ni.7z" "%%i"
First, I suggest opening help file 7zip.chm in program files directory of 7-Zip with a double click. Open on Contents tab the list item Command Line Version and next the list item Commands and click on l (List) to open the help page for listing archive file contents.
The batch file below uses 7-Zip with the command l with the switches -i (include) and -slt (show technical information). The batch file expects to find the *.cue file in root of each *.7z archive file and therefore does not use the option to search for *.cue files in archive recursively.
Second, open a command prompt window in directory containing the about 600 *.7z archive files and run the command line:
"%ProgramFiles(x86)%\7-Zip\7z.exe" l -i!*.cue -slt "Crash Bandicot PSX 1995.7z"
7-Zip outputs the list of *.cue files inside archive Crash Bandicot PSX 1995.7z with showing technical information. Now with knowing how the output of 7-Zip (of version 16.04 as used by me) looks like, the options used in batch file for second FOR loop can be understood better.
The batch file below searches only in current directory for *.7z files and renames all files containing a *.cue file if name does not already match.
Insert DIR option /S (search also in subdirectories) after /B (bare format) in case of the *.7z files are not all in current directory, but in current directory and its subdirectories.
Here is the comment batch file for this archive file renaming task:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Prepend folder path to 7z.exe temporarily to local copy of environment
rem variable PATH to be able to call 7z.exe without full path enclosed in
rem double quotes as this would make the FOR command line running 7z.exe
rem really very difficult.
set "PATH=%ProgramFiles(x86)%\7-Zip;%PATH%"
set "PauseOnWarning=0"
rem Search in current directory for *.7z files using command DIR and not FOR
rem directly and call for each found file the subroutine RenameArchiveFile
rem with file name enclosed in double quotes. It is important not using FOR
rem for searching for *.7z files as the found *.7z files are renamed while
rem executing the loop. A *.7z file could be easily processed more than once
rem on using command FOR directly. Better is in this case to use command DIR
rem which first search for all *.7z files (including hidden ones which FOR
rem would not do) and then outputs the names of all found files being
rem processed next by command FOR. So it does not matter that file names
rem change while FOR processes the list of file names output by DIR.
for /F "delims=" %%I in ('dir /A-D /B *.7z 2^>nul') do call :RenameArchiveFile "%%I"
rem Output an empty line and halt batch file execution if any warning
rem was output while processing the *.7z files in the subroutine.
if %PauseOnWarning% == 1 echo/ & pause
rem Restore previous command line environment and exit batch processing.
endlocal
goto :EOF
rem RenameArchiveFile is a subroutine called with name of the archive file
rem enclosed in double quotes. The file name can be with or without path.
rem 7-Zip is executed to output the list of *.cue files with showing
rem technical information for easier parsing the output lines. Any error
rem message output by 7-Zip is suppressed by redirecting them from STDERR
rem to device NUL. It is not expected that 7-Zip outputs an error at all.
rem The first 14 lines are always skipped by command FOR. The next lines
rem are split up into two substrings using space and equal sign as string
rem delimiters. The first substring is assigned to loop variable A and
rem everything after first substring and 1 to n spaces/equal signs is
rem assigned to loop variable B. There is hopefully no *.cue file which
rem begins unusually with an equal sign or a space character.
rem If the first substring (token) from current line assigned to loop
rem variable A is case-sensitive the word Path, it is expected that the
rem second substring (token) assigned to loop variable B is the name of
rem the *.cue file found in the current archive file. In this case the
rem file name is assigned to an environment variable and loop is exited
rem with a jump to label HaveFileName.
rem A warning message is output if no *.cue file could be found in archive.
:RenameArchiveFile
for /F "skip=14 tokens=1* delims== " %%A in ('7z.exe l -i!*.cue -slt %1 2^>nul') do (
if "%%A" == "Path" (
set "FileName=%%B"
goto :HaveFileName
)
)
echo Warning: Could not find a *.cue file in: %1
set "PauseOnWarning=1"
goto :EOF
rem A *.cue file was found in current archive. The file extension cue
rem at end is replaced by 7z for the new name of the archive file.
rem First it is checked if the current archive file has already the file
rem name of the *.cue file inside the archive in which case the subroutine
rem RenameArchiveFile is exited resulting in processing of batch file being
rem continued on main (first) FOR loop.
rem If there is no *.7z file in directory of current archive file with
rem the new name, the current archive file is renamed to new name and
rem subroutine RenameArchiveFile is exited without further processing.
rem But if a different archive file than current archive file has already
rem the new archive file name, the subroutine outputs a 3 lines warning
rem and exits without renaming the current archive file. The user has to
rem handle this file name collision.
:HaveFileName
set "FileName=%FileName:~0,-3%7z"
if "%FileName%" == "%~nx1" goto :EOF
if not exist "%~dp1%FileName%" ren %1 "%FileName%" & goto :EOF
echo Warning: Could not rename %1
echo to "%FileName%"
echo because a file with that name already exists.
set "PauseOnWarning=1"
goto :EOF
It might be a good idea to first insert command echo left of rename command ren near and of the batch file and insert pause in a line between endlocal and goto :EOF to test how the *.7z files would be renamed without really doing it.
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.
7z ... 7-Zip is not using standard Windows syntax for options, but outputs a brief help on running without any parameter or with just -h as parameter.
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
rem /?
ren /?
set /?
setlocal /?
Read also the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul used in this batch file twice with escaping the redirection operator > with caret character ^ to get > interpreted as literal character on parsing FOR command line by Windows command interpreter and later on execution of DIR command line by FOR as redirection operator.
And see Single line with multiple commands using Windows batch file for understanding what an ampersand & means in command lines if not being present within a double quoted string.
For the purposes of saving space and organizing, I'm zipping bunch of files in my local and networked folders. They are mainly CAD files, like stp, igs, etc.
There are already existing zip files and some are extracted by other users, but the zip file still exists on the folders, which eats up space.
Is there a command line zip, rar, 7z. etc. to find out if an archive file contains only 1 file?
I'd like to figure this out as I'll extract the archives with single files in to the current directory whilst extracting archives with 1+ files to \archivename\ folder. Otherwise one folder with 30 STP files, will suddenly have 30 folders and 30 files extracted in them which I don't want.
I currently use a batch file with WinRAR to extract and another program to check for duplicates, then WinRAR batch to re-zip them based on file extension. (Reason: people use different archive methods and there are duplicates of files all over.)
Sample batch files:
for /F "delims=," %%f in ('dir *.stp /B' ) do (%path% a -afzip -r- -m5 -ed -ep -or -tl -y -df "%%f".zip "%%f")
for /F "delims=;" %%f in ('dir *.7z /B /S' ) do (%path% x -OR -ilogC:\Users\XXXX\Desktop\myLog.txt "%%f" "%%~dpf"\"%%~nf"\)
Once I can check for number of files in a zip, I'll add a recursive function.
I can use NTFS compression, but I also want to organize the folders, some folder have 1000 files in them, I surely want to reduce that to 1. These are mainly for archiving purposes.
Any help or thought would be appreciated.
I suggest the following commented batch file for this task:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Extract all 7-Zip, RAR and ZIP archives in current directory into
rem subdirectories with name of archive file as name for subdirectory (-ad)
rem with running WinRAR for extraction in background (-ibck) which means
rem minimized to system tray with restoring also last access time (-tsa)
rem and creation time (-tsc) if existing in archive file and with skipping
rem files on extraction perhaps already present in the subdirectory with
rem same last modification time (-u), but overwriting automatically older
rem files in subdirectory if archive file contains an existing file with
rem a newer last modification time (-y) ignoring all errors (also -y).
for %%I in (7z rar zip) do "%ProgramFiles%\WinRAR\WinRAR.exe" x -ad -ibck -tsa -tsc -u -y *.%%I
rem If a subdirectory contains only 1 file, move that file to the current
rem directory with overwriting a perhaps already existing file with same
rem name in current directory and then remove the subdirectory.
for /D %%I in (*) do call :CheckSubDir "%%I"
rem Exit processing of the batch file without fall through to subroutine.
endlocal
goto :EOF
rem The subroutine CheckSubDir first checks for directories in directory
rem passed as parameter to the subroutine. A directory containing at
rem least one subdirectory is kept without any further processing.
rem If the directory does not contain a subdirectory, it searches for files
rem in the directory. If there are at least 2 files, the directory is kept
rem without any further processing.
rem But if the directory contains only 1 file, this file is moved to
rem current directory. Then the empty directory is deleted before exiting
rem the subroutine and continue batch file processing in calling loop.
rem Each directory containing no subdirectory and no file is removed, too.
:CheckSubDir
for /F "delims=" %%D in ('dir /AD /B "%~1\*" 2^>nul') do goto :EOF
setlocal EnableDelayedExpansion
set FileCount=0
for /F "delims=" %%F in ('dir /A-D /B "%~1\*" 2^>nul') do (
set /A FileCount+=1
if !FileCount! == 2 endlocal & goto :EOF
set "FileName=%%F"
)
if %FileCount% == 1 move /Y "%~1\%FileName%" "%FileName%"
rd "%~1"
endlocal
goto :EOF
Please read the comments for details what this batch file does on execution using WinRAR.
The batch file contains much more comment lines than real command lines.
2>nul in the last two FOR loops redirects the error message output by command DIR to handle STDERR in case of no directory or no file found to device NUL to suppress it. The redirection operator > must be escaped here with character caret ^ to be interpreted as redirection operator on execution of DIR command line and not already on parsing the FOR command line.
WinRAR supports many archive types on extraction. But WinRAR.exe is a GUI application and therefore does not support listing the contents of an archive file to console as Rar.exe supports.
The console version Rar.exe as well as free console application UnRAR.exe support both listing the archive file contents to handle STDOUT in various formats.
This difference on supported commands between WinRAR.exe and Rar.exe/UnRAR.exe can be seen by opening in WinRAR the help by clicking in menu Help on menu item Help topics, opening on help tab Contents the list item Command line mode, opening the list item Commands, clicking on list item Alphabetic commands list and comparing this list with the commands listed and described in text file Rar.txt in program files folder of WinRAR which is the manual for the console version.
Rar.txt lists and describes:
l[t[a],b] ... List archive contents [technical [all], bare]
v[t[a],b] ... Verbosely list archive contents [technical [all], bare].
Help of WinRAR does whether contain command l nor command v.
It would be of course also possible to run Rar.exe or UnRAR.exe on each *.rar file with command lb, count the number of lines output as done in above batch file to count the files and extract the *.rar archive file depending on the line count to current directory (1 line only) or to a subdirectory.
But it should be taken into account that on using bare list format and only 1 line output this line can be the name of an archived file or the name of an archived empty folder. The solution would be using standard list command and more analyze the attributes as well because a directory has attribute D while file does not have this attribute.
And for *.7z and *.zip files the same must be coded using 7z.exe or 7za.exe. The help of 7-Zip describes also the available commands and switches like the help of WinRAR.
But all those efforts do not make much sense in comparison to posted solution as the archive file has to be extracted at all and moving a file is done very fast as just the entry in file allocation table is modified and no data are copied or moved at all.
Running 7-Zip or Rar separately for first just listing each archive file contents, analyzing the list, and running 7-Zip or Rar once again on archive file for extraction is much slower than running WinRAR just 3 times (or less) to extract all archives and then move some files and remove some directories.
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 /?
dir /?
echo /?
endlocal /?
for /?
goto /?
move /?
rd /?
set /?
setlocal /?
See also the Microsoft TechNet article Using command redirection operators.
Taking the question literal the following batch uses 7z.exe (has to be reachable via the Path) list (l)-option to get the number of files included in the archive by filtering the last line.
#Echo off
Set Base=q:\Test
Pushd "%Base%"
For /f "delims=" %%A in (
'Dir /B/S/A-D *.zip *.7z *.rar'
) Do For /f "tokens=5" %%B in (
' 7z.exe l "%%~A" ^| findstr "files$" '
) Do If %%B equ 1 (
Echo Archive %%A contains 1 file
) else (
Echo Archive %%A contains %%B files
)
Popd
Sample Output:
Archive q:\Test\archiv.7z contains 135 files
Archive q:\Test\PoSh\powershellitunes\PowerScript-itunes.7z contains 1 file
Archive q:\Test\PoSh\_pdf_itextsharp\extract_pdf_pages_into_new_323689.zip contains 3 files
Archive q:\Test\_StackOverflow\Noodles\Filter0.8.zip contains 4 files
Archive q:\Test\2016\12\16\Path.rar contains 7 files
Archive q:\Test\_AllHelp.Win\allhelp.zip contains 7 files
Archive q:\Test\2017-02\pkzipc_40.rar contains 10 files