Using some components I found here, I have built a batch file to loop through a directory tree starting from the directory where the batch file runs.
The batch file works as expected but I need to capture the output from the cmd.exe command CD into a file that I created earlier in the run.
The problem is that if I attempt to redirect the standard output into the .txt file I only see the first found directory.
I have found some code which uses PowerShell, to pull the listing from the Command Prompt screen, but to me this is inelegant, (although it seems to work).
I have read the material on setlocal enabledelayedexpansion but it appears to be above my paygrade as I haven't been able to make it work.
The working code is below, with a Remark where I think the export to the .txt file should go.
Help would be appreciated.
Rem Recursively Traverse a Directory Tree
Rem Notes:
Rem "For /r" command can be used to recursively visit all the directories in
Rem a directory tree and perform a command in each subdirectory.
Rem In this case, save the output to a text file
Rem for /r = Loop through files (Recurse subfolders).
Rem pushd = Change the current directory/folder and store the previous folder/path for
Rem use by the POPD command.
Rem popd = Change directory back to the path/folder most recently stored by the PUSHD
Rem command.
#echo off
CLS
echo.
echo.
Rem FirstJob - Generate a date and save in the work file.
Rem Grab the date/time elements and stuff them into a couple of variables
set D=%date%
set T=%time%
set DATETIME=%D% at %T%
Rem OK. We now have the date and time stuffed into the variable DATETIME
Rem so now stick it into our work file along with a heading.
Echo List of Found Directories > DirList.txt
Echo %DATETIME% >> DirList.txt
echo. >> DirList.txt
echo. >> Dirlist.txt
Rem SecondJob - Do the looping stuff and save found directories to file.
Rem Start at the top of the tree to visit and loop though each directory
for /r %%a in (.) do (
Rem enter the directory
pushd %%a
CD
Rem ------------------ direct Standard Output to the file DirList.txt -----------------
Rem exit the directory
popd
)
: END
Rem All finished
Echo Done!
exit /b
The additional lines of code when added to the above scrip before the :END marker. which did produce the wanted output were:
powershell -c "$wshell = New-Object -ComObject wscript.shell; $wshell.SendKeys('^a')
powershell -c "$wshell = New-Object -ComObject wscript.shell; $wshell.SendKeys('^c')
powershell Get-Clipboard>>DirList.txt
The problem is your pushd command, because you change the current directory, the file dirlist.txt must use an absolute path, else you create it in every pushed directory.
I used %~dp0 here, it's the path of the batch file itself.
You could try
cd >> %~dp0\dirlist.txt
Or just
echo %%a >> %~dp0\dirlist.txt
Or you could use a single redirecton of the complete bock
(
for /r %%a in (.) do (
pushd %%a
echo %%a
popd
)
) > dirlist.txt
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
)
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 requirement is - i need to read the filename from an input folder say - C:\Encrypt\In and pass it to the command java.exe -jar D:\SYS\src\PI\IN\Cryptage.jar -rc4 -crypt D:\SYS\src\PI\IN\Decrypt\ D:\src\PI\IN\Encrypt\ %VAR1%%VAR2%
i tried doing the one below - but no luck
set VAR1=FOR /R C:\Encrypt\In %F in (*.*) do echo %~nF
set VAR2=ABCD
echo %VAR1%%VAR2% (concatenate the filename with "ABCD" as constant)
java.exe -jar D:\SYS\src\PI\IN\Cryptage.jar -rc4 -crypt D:\SYS\src\PI\IN\Decrypt\ D:\src\PI\IN\Encrypt\ %VAR1%%VAR2%
(pass it here - so that each time a file comes in the input directory the variables can pick up the file names dynamically through the variables)
echo %VAR1%%VAR2% is not working.
Thanks anyway - i achieved it through this :- cd C:\Encrypt\In\ for %%f in (.) do ( rem echo %%~nfAPSI set v=%%~nfAPSI ) echo %v%
Here is a commented batch code for your task:
#echo off
set "ScanFolder=C:\Encrypt\In"
rem The loop runs command DIR to get a list of files with archive attribute set.
rem Directories are ignored even if archive attribute is set on a directory.
rem On each file with archive attribute currently set the archive attribute
rem is removed from file and then the command is started to process the file.
rem After all files with archive attribute were processed, the batch file
rem waits 5 seconds before scanning the folder again. The loop is infinite
rem and can be breaked only by pressing Ctrl+C or closing command prompt
rem window to stop command line interpreter.
:Loop
for /F "delims=" %%F in ('dir /AA-D /B "%ScanFolder%" 2^>nul') do (
%SystemRoot%\System32\attrib.exe -A "%ScanFolder%\%%~nxF"
java.exe -jar D:\SYS\src\PI\IN\Cryptage.jar -rc4 -crypt D:\SYS\src\PI\IN\Decrypt\ D:\src\PI\IN\Encrypt\ "%ScanFolder%\%%~nxF"
)
%SystemRoot%\System32\ping.exe -n 6 127.0.0.1>nul
goto Loop
java.exe should be called with full path enclosed in double quotes if possible as in this case command line interpreter would not always need to search for it in the folders of environment variable PATH.
Note: The batch file calls the new file with full path, file name and extension without anything appended. Of course you can replace %%~nxF at end of line calling java.exe also with %%~nFABCD if this is necessary in your environment.
For an explanation of the used commands and how they work in detail open a command prompt window and execute following commands to see the help of those commands:
attrib /?
dir /?
for /?
ping /?
I want to be able to use the "Send to" function (When right clicking a file) with this batch file.
It needs to create a folder, with the name of the file, for each of the selected files, in the same directory as the file itself. (No moving of the file needed)
The following code has helped, but this creates folders for all files in the directory and places it in the directory of the batch file.
#echo off
pushd %~dp0
for /f "delims=" %%a in ('dir /b') do (
if not "%%~fa"=="%~f0" (
md "%%~na" 2>nul
)
)
popd
I believe using the following function will be needed for the directory of the files but not sure about how to call it.
%CD%
I am rather new to batch files so any extra explanation would be helpful, but not necessary.
Even if it can only run on one file at a time, that will be great since it needs to be no a chosen file basis.
Here goes to learning on the go and thanks for any help!
This should do what you are looking for. Give this script a try in your Send To menu:
#ECHO OFF
SETLOCAL
:ProcessFile
REM Check if there are any files to process.
IF "%~1"=="" GOTO :EOF
REM Process the current file.
SET NewDir="%~dpn1\"
REM Create the directory if it doesn't already exist.
IF NOT EXIST %NewDir% MKDIR %NewDir%
REM Move to the next selected file.
SHIFT /1
REM Recurse.
GOTO ProcessFile
ENDLOCAL
I am really new to batch file coding and need your help.
I've these directories:
c:\rar\temp1\xy.jpg
c:\rar\temp1\sd.jpg
c:\rar\temp1\dd.jpg
c:\rar\temp2\ss.jpg
c:\rar\temp2\aa.jpg
c:\rar\temp2\sd.jpg
c:\rar\temp3\pp.jpg
c:\rar\temp3\ll.jpg
c:\rar\temp3\kk.jpg
And I want to compress them to this
c:\rar\temp1\temp1.rar
c:\rar\temp2\temp2.rar
c:\rar\temp3\temp3.rar
How could this be done using WinRAR?
This can be done also with WinRAR without using a batch file, not exactly as requested, but similar to what is wanted.
Start WinRAR and navigate to folder c:\rar\.
Select the folders temp1, temp2 and temp3 and click on button Add in the toolbar.
As archive name specify now the folder for the RAR archives, for example c:\rar\.
Switch to tab Files and check there the option Put each file to separate archive.
Click on button OK.
WinRAR creates now three RAR archives with the file names temp1.rar, temp2.rar and temp3.rar in folder c:\rar\ with each archive containing the appropriate folder with all files and subfolders.
The list of files to add can be changed also on tab Files by entering for example *.txt in Files to exclude to ignore text files in the three folders on creating the archives.
And finally it makes sense to enter *.jpg on tab Files in edit field below Files to store without compression as JPEG files usually contain already compressed data and therefore WinRAR cannot really compress the data of the files further.
Here is also a batch file solution to move the files in all non-hidden subfolders of c:\rar\ and their subfolders into an archive file with name of the subfolder created in each subfolder as requested.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "RAREXE=Rar.exe"
if exist "%RAREXE%" goto CreateArchives
if exist "%ProgramFiles%\WinRAR\Rar.exe" set "RAREXE=%ProgramFiles%\WinRAR\Rar.exe" & goto CreateArchives
if exist "%ProgramFiles(x86)%\WinRAR\Rar.exe" set "RAREXE=%ProgramFiles(x86)%\WinRAR\Rar.exe" & goto CreateArchives
for /F "skip=2 tokens=1,2*" %%I in ('%SystemRoot%\System32\reg.exe query "HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\WinRAR.exe" /v Path 2^>nul') do (
if /I "%%I" == "Path" if exist "%%~K\Rar.exe" for %%L in ("%%~K\Rar.exe") do set "RAREXE=%%~fL" & goto CreateArchives
)
for /F "skip=2 tokens=1,2*" %%I in ('%SystemRoot%\System32\reg.exe query "HKCU\Software\Microsoft\Windows\CurrentVersion\App Paths\WinRAR.exe" /v Path 2^>nul') do (
if /I "%%I" == "Path" if exist "%%~K\Rar.exe" for %%L in ("%%~K\Rar.exe") do set "RAREXE=%%~fL" & goto CreateArchives
)
for /F "delims=" %%I in ('%SystemRoot%\System32\where.exe Rar.exe 2^>nul') do set "RAREXE=%%I" & goto CreateArchives
echo ERROR: Could not find Rar.exe!
echo/
echo Please define the variable RAREXE at top of the batch file
echo "%~f0"
echo with the full qualified file name of the executable Rar.exe.
echo/
pause
goto :EOF
:CreateArchives
set "Error="
for /D %%I in ("c:\rar\*") do (
echo Creating RAR archive for "%%I" ...
"%RAREXE%" m -# -cfg- -ep1 -idq -m3 -msgif;png;jpg;rar;zip -r -s- -tl -y -- "%%I\%%~nxI.rar" "%%I\"
if errorlevel 1 set "Error=1"
)
if defined Error echo/& pause
endlocal
The lines after set "RAREXE=Rar.exe" up to :CreateArchives can be omitted on definition of environment variable RAREXE with correct full qualified file name.
Please read the text file Rar.txt in the WinRAR program files folder for an explanation of RAR command m and the used switches. The question does not contain any information with which options the RAR archives should be created at all.
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 /? ... explains %~f0 ... full name of batch file
echo /?
endlocal /?
for /?
goto /?
if /?
pause /?
reg /?
reg query /?
set /?
setlocal /?
where /?
See also single line with multiple commands using Windows batch file for an explanation of the operator &.
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 the three FOR command lines to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded reg or where command line with using a separate command process started in background.
This script can work as well:
#echo off
for %%a in ("C:\rar\temp1" "C:\rar\temp2" "C:\rar\temp3") do (
pushd "%%~a"
"C:\Program Files\WinRAR\rar.exe" a -r temp.rar *
popd
)
In Python v3.x:
Tested on Python v3.7
Tested on Windows 10 x64
import os
# NOTE: Script is disabled by default, uncomment final line to run for real.
base_dir = "E:\target_dir"
# base_dir = os.getcwd() # Uncomment this to run on the directory the script is in.
# Stage 1: Get list of directories to compress. Top level only.
sub_dirs_raw = [os.path.join(base_dir, o) for o in os.listdir(base_dir) if os.path.isdir(os.path.join(base_dir, o))]
# Stage 2: Allow us exclude directories we do not want (can omit this entire section if we wish).
dirs = []
for d in sub_dirs_raw:
if "legacy" in d or "legacy_old" in d:
continue # Skip unwanted directories
print(d)
dirs.append(d)
# Stage 3: Compress directories into .rar files.
for d in dirs:
os.chdir(d) # Change to target directory.
# Also adds 3% recovery record using "-rr3" switch.
cmd = f"\"C:\Program Files\\WinRAR\\rar.exe\" a -rr3 -r {d}.rar *"
print(cmd)
# Script is disabled by default, uncomment this next line to execute the command.
# os.system(cmd)
Notes:
Script will do nothing but print commands, unless the final line os.system(cmd) is uncommented by removing the leading # .
Run the script, it will print out the DOS commands that it will execute. When you are happy with the results, uncomment final line to run it for real.
Example: if there was a directory containing three folders mydir1, mydir2, mydir3, it would create three .rar files: mydir1.rar, mydir2.rar, mydir3.rar.
This demo code will skip directories with "legacy" and "legacy_old" in the name. You can update to add your own directories to skip.
To execute the script, install Python 3.x, paste the lines above into script.py, then run the DOS command python script.py from any directory. Set the target directory using the second line. Alternatively, run the script using PyCharm.
This should work it also checks if the files were compressed alright.
You may need to change this part "cd Program Files\WinRAR" depending on where winrar is installed.
#echo Off
Cd\
cd Program Files\WinRAR
rar a -r c:\rar\temp1\temp1.rar c:\rar\temp1\*.jpg c:\rar\temp1\
if "%ERRORLEVEL%"=="0" ( Echo Files compressed
) Else Echo Failed
rar a -r c:\rar\temp2\temp2.rar c:\rar\temp2\*.jpg c:\rar\temp2\
if "%ERRORLEVEL%"=="0" ( Echo Files compressed
) Else Echo Failed
rar a -r c:\rar\temp3\temp3.rar c:\rar\temp3\*.jpg c:\rar\temp3\
if "%ERRORLEVEL%"=="0" ( Echo Files compressed
) Else Echo Failed
Pause
Below Script will compress each folder as a RAR file within the current directory with very useful info while compressing a large size of data.
#echo off
#for /D %%I in (".\*") do echo started at %date% %time% compressing... "%%I" && #"%ProgramFiles%\WinRAR\Rar.exe" a -cfg- -ep1 -inul -m5 -r -- "%%I.rar" "%%I\"
echo "Completed Successfully !!!"
pause