Outcome is to change to directory after searching for the file via DIR through cmd
Location of file is C:\Folder
is the following code possible?
set /a variable= dir document.doc /s /p
cd %%variable%%
Change directory to C:\Folder
try this:
for /f "delims=" %%# in ('dir document.doc /s /b') do (
set "new_dir=%%~dp#"
)
cd /d "%new_dir%"
Run in a command prompt window set /? and read the output help carefully from first to last page.
set /A is for evaluating an arithmetic expression. So the string after set /A is interpreted by Windows command line interpreter as arithmetic expression (formula).
set /a variable= dir document.doc /s /p
This command line outputs on execution the error message missing operator because dir is interpreted as a variable name and also document.doc both most likely not existing and therefore replaced by 0 on evaluating the expression. But cmd.exe expects an operator between those two environment variable names and as there is none like / before variable s, the error message is output.
It is not possible to assign possible multi-line output of a command line like dir document.doc /s /p to an environment variable with command SET.
In a batch file you can use this code:
#echo off
for /R %%I in ("document*.doc") do cd /D "%%~dpI" & goto FoundFile
echo Could not find any document*.doc in %CD% or its subdirectories.
pause
goto :EOF
:FoundFile
echo Found a file document*.doc in directory %CD%.
pause
Command FOR searches for any non hidden file matching the pattern document*.doc in current directory and all non hidden subdirectories. A wildcard character like * or ? must be specified to run a search for a file. If a file is found, the command CD is executed to change to directory of the file and the loop is exited with a jump to a label.
Another solution to really search only for file document.doc:
#echo off
for /F "delims=" %%I in ('dir "document*.doc" /A-D /B /S 2^>nul') do cd /D "%%~dpI" & goto FoundFile
echo Could not find file document.doc in %CD% or its subdirectories.
pause
goto :EOF
:FoundFile
echo Found file document.doc in directory %CD%.
pause
This example shows how to run a command line like dir "document*.doc" /A-D /B /S 2>nul in a separate command process started by FOR with cmd.exe /C with capturing all output lines written to handle STDOUT while in this case redirecting an error message written to handle STDERR to device NUL to suppress it.
The captured output is next processed by FOR line by line with skipping with default options all empty lines and lines starting with a semicolon and splitting up each line into substrings (tokens) using space and tab as delimiters with assigning only first substring to specified loop variable I. This line splitting behavior is disabled by using "delims=" which defines an empty list of delimiters and so no line splitting is possible anymore. In this case it is impossible that a line output by DIR starts with ; and so we don't need to care about eol (end of line) option.
%%~dpI expanding to just drive and path of current file name with path can be also assigned to an environment variable for example with set "FilePath=%%~dpI". And the environment variable FilePath can be referenced in rest of the batch file either with immediate expansion using %FilePath% or with delayed expansion using !FilePath! enclosed the entire argument string containing this variable reference in double quotes for working also for file paths containing a space or one of these characters: &()[]{}^=;!'+,`~
Both batch codes always changes to first found document*.doc respectively document.doc file and ignoring all other files matching the pattern respectively with same name perhaps also found by FOR or DIR in other directories in searched directory tree. The first solution is faster on a large directory tree needs to be searched for the file. But first solution ignores hidden subdirectories and can change to a directory containing for example document_1.doc instead of document.doc.
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.
cd /?
dir /?
echo /?
for /?
goto /?
pause /?
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.
Related
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'm trying to find recursively all "MyApp.exe" apps in "C:\Builds" folder and run the apps with "createdatabase closeimmediately" arguments/parameters.
What I search so far:ForFiles Microsoft docs
Here is the forfiles pattern:
forfiles [/p <Path>] [/m <SearchMask>] [/s] [/c "<Command>"] [/d [{+|-}][{|}]]
Here is what I have:
forfiles /p c:\Builds /s /m MyApp.exe /c "cmd /c start #path" "createdatabase closeimmediately"
If I run above script, it is showing error:
ERROR: Invalid argument/option - 'createdatabase closeimmediately'.Type "FORFILES /?" for usage.
If I run without parameteres, it finds apps correctly and runs, but I need to run with parameters:
forfiles /p c:\Builds /s /m MyApp.exe /c "cmd /c start #path"
How can I run apps with parameters in ForFiles?
I know this was mentioned in the comments, but the comments are becoming too long for me to post a decent comment still, so here is an answer. This should do exactly what you want, it will recursively search for the file and execute if exists.
#echo off
for /r "c:\Builds" %%i in (myapp.exe) do if exist "%%i" "%%i" createdatabase closeimmediately
a slightly different way, find all executables, and launch if the name matches myapp.exe:
for /r "c:\Builds" %%i in (*.exe) do if /I "%%~nxi" == "myapp.exe" "%%I" createdatabase closeimmediately
There are multiple methods possible to search for MyApp.exe in C:\Build and all subfolders and execute the found executable with the two parameters createdatabase and closeimmediately.
The first solution uses command FOR to search for any file matching the wildcard pattern MyApp*.exe in C:\Build and any non-hidden subfolder.
For usage in a batch file:
for /R "C:\Build" %%I in ("MyApp*.exe") do if /I "%%~nxI" == "MyApp.exe" "%%I" createdatabase closeimmediately
For usage in command prompt window:
for /R "C:\Build" %I in ("MyApp*.exe") do #if /I "%~nxI" == "MyApp.exe" "%I" createdatabase closeimmediately
It is necessary that the string inside the round brackets contains at least one * or ? to define a wildcard pattern. Otherwise FOR would not search for files with name MyApp.exe on using just "MyApp.exe" in C:\Build and all its subfolders. It would simply append the string "MyApp.exe" (with the double quotes) to folder path of every folder found in C:\Build folder structure and would assign folder path + "MyApp.exe" to loop variable I and execute the command line referencing the loop variable.
The IF condition is used to make sure that only MyApp.exe is executed and not for example MyAppOther.exe found by chance also by FOR with wildcard pattern MyApp*.exe. The string comparison is done case-insensitive because of /I.
It would be also possible to use a different wildcard pattern like MyApp.exe*. This could reduce the number of false positives. But for security the IF condition should be nevertheless used.
The second solution is using just MyApp.exe and check if a file with that name really exists in the given folder path before executing it.
For usage in a batch file:
for /R "C:\Build" %%I in (MyApp.exe) do if exist "%%I" "%%I" createdatabase closeimmediately
For usage in command prompt window:
for /R "C:\Build" %I in (MyApp.exe) do #if exist "%I" "%I" createdatabase closeimmediately
MyApp.exe is specified in round brackets without being enclosed in " as otherwise the string assigned to loop variable I would be for example C:\Build\"MyApp.exe" and not C:\Build\MyApp.exe. By automatic error correction the string value C:\Build\"MyApp.exe" might also work depending on which string is really used instead of MyApp.exe. But this is not really a safe method and does not work if the string MyApp.exe contains a space, comma, semicolon, or other characters like &()[]{}^=;!'+,`~.
The third solution is using the command DIR for searching for MyApp.exe without a wildcard pattern to find only files with exactly that name and let FOR execute the found executables with that name.
For usage in a batch file:
for /F "delims=" %%I in ('dir "C:\Build\MyApp.exe" /A-D-H /B /S 2^>nul') do "%%I" createdatabase closeimmediately
For usage in command prompt window:
for /F "delims=" %I in ('dir "C:\Build\MyApp.exe" /A-D-H /B /S 2^>nul') do #"%I" createdatabase closeimmediately
In comparison to FOR the command DIR really searches for files with name MyApp.exe even on argument string not containing a wildcard character like * or ?.
FOR executes the DIR command line in a separate command process started with cmd.exe /C in background and captures everything written to handle STDOUT of this command process.
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.
2>nul is used to suppress the error message output by DIR to handle STDERR by redirecting it to device NUL if no file MyApp.exe could be found in C:\Build or its subdirectories.
DIR outputs because of /B and /S just the full qualified file name, i.e. file path + file name + file extension, of every found MyApp.exe line by line.
FOR processes the captured output line by line with skipping empty lines and lines starting with a semicolon. Such lines are surely not output by DIR with the used options.
FOR would also split up each line into substrings (tokens) on spaces/tabs and would assign only first substring to loop variable I. This string splitting behavior is not wanted here as a folder name could contain one or more spaces. For that reason FOR option delims= is used to define an empty list of delimiters which disables the line splitting behavior.
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.
dir /?
for /?
if /?
I want to make a batch or cmd file to automatically select the latest file in the directory D:\Romexis_Bilder\romexis_SQL_Backup. These are ZIP SQL backup files that are generated two times daily in the format yymmddhhmm.zip, e.g Romexis_db201805271200.zip on a server running Windows 2016 Server.
The latest added file to the directory (result of FOR /F) should then be used in SQL RESTORE (backup and ftp program Windows).
The idea was to use the FOR command
My draft:
Go into the directory:
pushd "D:\Romexis_Bilder\romexis_SQL_Backup"
Find the latest file. (I don't really know how to set the parameters here.)
for /f "tokens=*" %% in ('dir /D:\Romexis_Bilder\romexis_SQL_Backup /od') do set newest=%%D:\Romexis_Bilder\romexis_SQL_Backup
The result of FOR should be used in *.zip
cd C:\Program Files (x86)\Pranas.NET\SQLBackupAndFTP\
SqlRestore D:\Romexis_Bilder\romexis_SQL_Backup\*.zip -db Romexis_db -srv .\ROMEXIS -pwd password disconnect Romexis_db
I stuck with FOR, but don't know if there would also be another possibility.
I don't know if the last command line in question is really correct. I have some doubts output this line.
But this code can be used to get the name of the newest *.zip file according to last modification date without path.
#echo off
set "BackupFolder=D:\Romexis_Bilder\romexis_SQL_Backup"
for /F "eol=| delims=" %%I in ('dir "%BackupFolder%\Romexis_db*.zip" /A-D-H /B /O-D /TW 2^>nul') do set "NewestFile=%%I" & goto DatabaseRestore
echo ERROR: Could not find any *.zip backup file in folder:
echo "%BackupFolder%"
echo/
pause
goto :EOF
:DatabaseRestore
cd /D "%ProgramFiles(x86)%\Pranas.NET\SQLBackupAndFTP"
SqlRestore.exe "%BackupFolder%\%NewestFile%" -db Romexis_db -srv .\ROMEXIS -pwd password disconnect Romexis_db
echo/
pause
FOR executes in a separate command process started with cmd.exe /C in background the command line:
dir "D:\Romexis_Bilder\romexis_SQL_Backup\*.zip" /A-D-H /B /O-D /TW 2>nul
DIR outputs to handle STDOUT of background command process
only names of non hidden files because of /A-D-H (attribute not directory and not hidden)
in bare format because of /B just the file name with file extension, but without file path
sorted reverse (newest first) by date because of /O-D
using write time (last modification time) because of /TW
in directory D:\Romexis_Bilder\romexis_SQL_Backup matching the pattern Romexis_db*.zip.
I recommend running this command line in a command prompt window to see at least once what DIR outputs.
DIR would output an error message to handle STDERR in case of no *.zip file found or the directory does not exist at all. This error message is suppressed by redirecting it to device NUL.
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.
FOR captures the output written to STDOUT and processes the output line by line with ignoring empty lines which do not occur here because of DIR with option /B does not output empty lines.
FOR with option /F would ignore lines starting with a semicolon by default. For that reason end of line character is redefined with eol=| from ; to a vertical bar which file names can't contain. eol=| would not be required in this case because of file name pattern Romexis_dbYYYMMDDhhmm.zip making it unlikely that a file name starts with a semicolon.
FOR with option /F would split up the lines into substrings using space/tab as delimiter and would assign for each line only first space/tab delimited string to specified loop variable I. This line splitting behavior is disabled by specifying an empty list of delimiters with delims=. delims= would not be required in this case because of file name pattern Romexis_dbYYYMMDDhhmm.zip making it unlikely that a file name contains a space character.
The name of the file output first by DIR which is the newest ZIP file in specified directory is assigned to environment variable NewestFile. And next the FOR loop is exited with a jump to label DatabaseRestore as all other file names output by DIR are of no interest for this task.
The command lines below the FOR command line are executed only if there is no *.zip file in specified directory which report this unexpected error case.
It would be also possible to use the DIR command line below in batch file because of file name pattern Romexis_dbYYYMMDDhhmm.zip:
dir "%BackupFolder%\Romexis_db*.zip" /A-D-H /B /O-N 2^>nul
The same command line for execution from within a command prompt window:
dir "D:\Romexis_Bilder\romexis_SQL_Backup\*.zip" /A-D-H /B /O-N 2>nul
The order of the file names in output is here reverse by name which results in printing first the Romexis_db*.zip with newest date/time in file name thanks to date/time format YYYMMDDhhmm.
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.
cd /?
dir /?
echo /?
for /?
goto /?
pause /?
set /?
See also:
Where does GOTO :EOF return to?
Single line with multiple commands using Windows batch file
#Mofi
Thanks you for all your work it helped a lot!
As you advised I used each command in command prompt first to see the outputs (adapted batch %%I to cmd %I and vice versa)
I'm now able to find the newest file in D:\Romexis_Bilder\romexis_SQL_Backup the result is processed an taken as variable into the restore of the database which is done with One-Click SQL Restore https://sqlbackupandftp.com/restore
I did some modification in syntax of your commands O:D since „- „ excludes, removed attribute /TW because it was only listing backups from 2017.
#echo off
set "BackupFolder=D:\Romexis_Bilder\romexis_SQL_Backup"
for /F "eol=| delims=" %I in ('dir "%BackupFolder%\Romexis_db*.zip" /A-D-H /B /O:D 2^>nul') do set "NewestFile=%I" & goto DatabaseRestore
echo ERROR: Could not find any *.zip backup file in folder:
echo "%BackupFolder%"
echo/
pause
goto :EOF
:DatabaseRestore
cd /D "%ProgramFiles(x86)%\Pranas.NET\SQLBackupAndFTP"
SqlRestore.exe "%BackupFolder%\%NewestFile%" -db Romexis_db -srv .\ROMEXIS -pwd password
echo/
pause
Maybe the ^ in 'dir "%BackupFolder%\Romexis_db*.zip" /A-D-H /B /O:D 2^>nul' is not correct in CMD but didn‘t seem affect the result.
It was really advance! Now the GUI of One-Click SQL Restore opens with the newest *zip . The only thing that I still need to get out, is the syntax in command prompt for the restore, now i still need to click on the restore button of the GUI. Or try it over Microsoft Visual Studio SQL or command line tool.
#MOFI no modifications are made to files from 2017 or other files at all, files are not overwritten or modified later, a new file is always created by the back up program 2 times a day with the naming romexis_dbYYYMMDDhhmm.ziptwo times a day. Will try /O-N
THANKS a lot fo you input
I'm making a simple batch script to process a large set of files and delete all I don't want. I want about 10% of the files and they all have certain tags in their names, lets say they contain apple, orange or pear. As there are so many files I want deleted, it would be quite time consuming to construct a FOR loop such as:
#echo off
pause
for /R %%i in ([the list of names of the files I don't want]) do del %%i
pause
So I was wondering if it is possible to code it such that it deletes all files which don't have names containing apple, orange or pear?
In other words all files should be deleted not containing in its name one of those 3 words.
I'm using a FOR loop because the files are nested within lots of subdirectories and I would like to preserve this structure after the unwanted files have been deleted.
You can use this batch file containing (more or less) just one command line:
#echo off
for /F "delims=" %%I in ('dir * /A-D /B /S 2^>nul ^| %SystemRoot%\System32\findstr.exe /I /R /V /C:"apple[^\\]*$" /C:"orange[^\\]*$" /C:"pear[^\\]*$"') do ECHO del "%%I"
This batch code does not really delete files because of command ECHO before del at end of the command line. Run this batch file from within a command prompt window with current directory being the root of the directory tree on which to delete unwanted files and verify the output. Then remove ECHO and run the batch file once again.
The command DIR searches because of /S in current directory and all subdirectories only for files because of /A-D (not directory attribute) matching the wildcard pattern * with output in bare format because of /B which means the output contains just the names of all found files with full path.
DIR outputs an error message to handle STDERR if it can't find any file. This error message is suppressed by redirecting it to device NUL with 2>nul. The redirection operator > must be escaped here with caret character ^ to be first interpreted as literal character on parsing the FOR command line by Windows command interpreter.
The output of DIR to handle STDOUT is piped with | to standard console application FINDSTR which searches in all lines case-insensitive because of /I for the regular expression strings because of /R specified with /C:. The redirection operator | must be escaped here also with ^.
An OR expression is not supported by FINDSTR like it is by other applications with regular expression support. But it is possible to specify multiple search strings as done here which are all applied on each line of the text to process one after the other until a positive match occurs or there is no more search string. That is a classic OR.
The regular expression word[^\\]*$ means:
word ... There must be found word (case-insensitive).
[^\\]* ... Find 0 or more characters NOT being a backslash.
$ ... The matching string must be found at end of line.
The regular expression is used to get a positive match only for lines on which the file name contains either apple OR orange OR pear, but NOT the file path.
But there is one more FINDSTR option: /V. This option inverts the result output to handle STDOUT. So output are the lines on which none of the 3 regular expressions produce a positive match.
The command FOR processes each line output by FINDSTR used as negative filter for output of DIR and runs for each line the command DEL respectively ECHO without splitting the line up into space/tab separated strings because of delims=.
And that's it.
It is necessary to prevent the batch file from deletion if being stored in the directory tree processed by command DIR. This can be achieved most easily with setting read-only attribute on batch file as command DEL does not delete files with read-only attribute set.
Example:
#echo off
rem Prevent batch file from deletion by setting read-only attribute on batch file.
%SystemRoot%\System32\attrib.exe +r "%~f0"
for /F "delims=" %%I in ('dir * /A-D /B /S 2^>nul ^| %SystemRoot%\System32\findstr.exe /I /R /V /C:"apple[^\\]*$" /C:"orange[^\\]*$" /C:"pear[^\\]*$"') do del "%%I"
rem It is safe to remove read-only attribute from batch file.
%SystemRoot%\System32\attrib.exe -r "%~f0"
The batch code above has no ECHO before command del and therefore really deletes files on execution.
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 /?
del /?
dir /?
echo /?
findstr /?
for /?
rem /?
Read also the Microsoft article about Using Command Redirection Operators for an explanation of | and 2>nul.
The batch command below will get me the newest file in a folder, however I'm only looking for files with a specific extension. Can anyone explain how to specify the extension (i.e. .jpg)
FOR /F "delims=|" %%I IN ('DIR "C:\Jenkins\Releases\C9metro" /B /O:D') DO SET NewestFile=%%I
I suggest to use the following lines:
FOR /F "eol=| delims=" %%I IN ('DIR "C:\Jenkins\Releases\C9metro\*.jpg" /A-D /B /O-D /TW 2^>nul') DO (
SET "NewestFile=%%I"
GOTO FoundFile
)
ECHO No *.jpg file found!
GOTO :EOF
:FoundFile
ECHO Newest *.jpg file is: "%NewestFile%"
The FOR loop can be also optimized to a single command line:
FOR /F "eol=| delims=" %%I IN ('DIR "C:\Jenkins\Releases\C9metro\*.jpg" /A-D /B /O-D /TW 2^>nul') DO SET "NewestFile=%%I" & GOTO FoundFile
ECHO No *.jpg file found!
GOTO :EOF
:FoundFile
ECHO Newest *.jpg file is: "%NewestFile%"
FOR starts in background one more cmd.exe with option /c and the command line within ' appended as additional arguments. There is executed in this case in background with Windows installed into C:\Windows:
C:\Windows\System32\cmd.exe /c DIR "C:\Jenkins\Releases\C9metro\*.jpg" /A-D /B /O-D /TW 2>nul
The internal command DIR searches now for file system entries in the specified directory matching the wildcard pattern *.jpg with following additional restrictions.
The parameter /A-D makes sure ignoring subdirectories which unusually end by chance also with the string .jpg.
The parameter /B turns on bare output format. In this case are output just the file names without path by command DIR never enclosed in " even on containing a space or one of these characters &()[]{}^=;!'+,`~ which require the file name string to be enclosed in " on further processing it by cmd.exe on other command lines.
The parameter /O-D results in getting output by DIR the found file names listed by date in reverse order from newest to oldest. In other words the file name of the newest file is output first and the file name of the oldest file is output last.
And parameter /TW makes sure the last modification time (write access) is used for ordering the found file names of the JPEG files in date order and not the creation or the last access time.
There could be no file name matching the wildcard pattern *.jpg in long or short 8.3 name in which case DIR outputs an error message to standard error stream STDERR of the background command process. cmd.exe processing the batch file would redirect that error output to its own standard error stream. That would result in displaying the error message in the console window not really useful for a user of the batch file. The usage of 2>nul instructs cmd.exe started in background to redirect the error message to device NUL to suppress it.
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.
FOR respectively cmd.exe processing the batch file captures all output written to standard output stream of in background started cmd.exe and processes it line by line after started cmd.exe closed itself after finishing executing the command DIR.
FOR on using option /F ignores always empty lines which is no problem here as DIR with the used options does not output empty lines.
FOR would next split up the lines into substrings using horizontal tab and normal space as string delimiters, would look next if first tab/space separated string begins with a semicolon in which case it would also ignore the entire line for further processing, and would otherwise assign just the first tab/space separated string to the specified loop variable I before running the commands in body of FOR.
The default line splitting behavior is not wanted as JPEG file names can contain one or more spaces. The usage of the option delims= defines an empty list of delimiters which turns off the line splitting behavior.
It is very unusual but nevertheless possible that a JPEG file name begins with ; (semicolon). Such a file name should not be ignored by FOR. The option eol=| defines a vertical bar as end of line character which no file name can contain ever. Microsoft lists the characters not allowed in a file name on Windows file systems in the documentation about Naming Files, Paths, and Namespaces.
So, the first file name output by DIR being from the newest file is assigned completely to the loop variable I and executed is the command SET to assign this string to the environment variable NewestFile.
The loop is exited on first found file matching the wildcard pattern *.jpg is assigned to the environment variable. That makes this method faster than letting DIR output the file names from oldest to first and assigning all file names one after the other to the variable NewestFile up to last found file which would be the newest file.
There is an error message output on DIR could not find any file and so FOR could not assign any file name string to the loop variable I and run once the commands SET and GOTO. Then the batch file processing is exited in this case as described in detail by Where does GOTO :EOF return to?
To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.
dir /?
echo /?
endlocal /?
for /?
goto /?
set /?
setlocal /?
See also:
Why is no string output with 'echo %var%' after using 'set var = text' on command line?
Single line with multiple commands using Windows batch file explaining the unconditional command operator & as used in the second example.
It's early... figured this one out:
'DIR "C:\Jenkins\Releases\C9metro\*.jpg"