How to create empty files in a loop with batch? - batch-file

I am having a problem on running a script to create empty files in a loop.
This is what have done so far:
#echo off
for /l %%a (1;1;20) do (echo m> ".mp4" c:\test)
pause
exit
Basically I have twenty names in a file on my desktop and I intend to create them as empty *.mp4 files in folder c:\test with the command echo m> .mp4. When I run the code above, it does not seem to work.

The following FOR loop can be used in the batch file to create empty files 1.mp4, 2.mp4, 3.mp4, ..., 20.mp4 in directory C:\test as suggested by rojo:
for /L %%I in (1,1,20) do type NUL >"C:\test\%%I.mp4"
And the next FOR loop can be used in the batch file to read the file names for the empty *.mp4 files to create from a list file on Windows desktop of current user as also suggested by rojo:
for /F "usebackq delims=" %%I in ("%USERPROFILE%\Desktop\List of Names.txt") do type NUL >"C:\test\%%I.mp4"
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.
for /?
type /?
Further the Microsoft article Using command redirection operators should be read explaining the redirection operator > and the SS64 page about NUL (null device).

Related

How can I find my error in the batch script?

The code below should archive some files by moving them into a subfolder. The batch file asks the user for the folder path. Then a subfolder should be created and if that was successful, it should move all files in the user input directory into the subdirectory. It works, but it closes although using pause. It does not output anything about a syntax error or anything at all. Please let me know if somebody notices something.
#echo off
SETLOCAL EnableDelayedExpansion
echo Insert path:
set /p path=
echo the path is %path%
cd %path%
echo The files will be moved to a new folder
pause
mkdir %path%\archived_files
IF EXIST "archived_files" (
for /f %%A in ('DIR /A /D /B') do (
echo %%A && move /Y %path%\%%A %path%\archived_files)
echo Folder "archived_files" created or already exists
) else ( echo Folder "archived_files" does not exist )
echo the files have been transferred
pause
ENDLOCAL
I suggest to use this batch file for the file moving task.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "BatchFileName=%~nx0"
set "BatchFilePath=%~dp0"
set "UserPath=%~1"
if defined UserPath goto ChangeFolder
:UserPrompt
set "UserPath="
set /P "UserPath=Enter path: "
rem Has the user not entered a string?
if not defined UserPath goto UserPrompt
rem Remove all double quotes from input string.
set "UserPath=%UserPath:"=%"
rem Has the user entered just one or more double quotes?
if not defined UserPath goto UserPrompt
:ChangeFolder
pushd "%UserPath%" 2>nul || (echo Folder "%UserPath%" does not exist.& goto UserPrompt)
for /F "eol=| delims=" %%I in ('dir /A-D /B 2^>nul') do goto CreateSubfolder
echo The folder does not contain any file to archive.& goto EndBatch
:CreateSubfolder
md "archived_files" 2>nul
if not exist "archived_files\" echo Failed to create subfolder: "archived_files"& goto EndBatch
rem It must be avoided that the currently running batch file is moved too.
set "ExcludeFileOption="
for %%I in ("%UserPath%\") do set "CurrentFolderPath=%%~dpI"
if "%CurrentFolderPath%" == "%BatchFilePath%" set "ExcludeFileOption= /XF "%BatchFileName%""
rem The command MOVE used with wildcard * does not move hidden files. A FOR loop
rem with MOVE is slow in comparison to usage of ROBOCOPY to move really all files.
rem The ROBOCOPY option /IS can be removed to avoid moving same files existing
rem already in the subfolder archived_files from a previous batch execution.
echo The files are moved to a new folder.
%SystemRoot%\System32\robocopy.exe . archived_files%ExcludeFileOption% /MOV /R:2 /W:5 /IS /NDL /NFL /NJH /NJS
if not errorlevel 2 if errorlevel 1 echo All files are moved successfully.
:EndBatch
popd
endlocal
pause
The batch file can be started with a a folder path as argument. So it is possible to right click on the batch file and click in opened context menu in submenu Send to on item Desktop (create shortcut). The .lnk file created on the user´s desktop can be renamed now also via context menu or key F2 to whatever name is useful like Archive files. Then the shortcut file can be cut with Ctrl+X and pasted with Ctrl+V in the folder %APPDATA%\Microsoft\Windows\SendTo to have in Send to context submenu the menu item Archive files. This makes it possible to right click on a folder and click in opened context menu in submenu Send to on Archive files to run the batch file without the need to enter a folder path manually.
The batch file prompts the user for the path if not started with a folder path as first argument or the folder cannot be found at all. This user prompt is done using a safe method. The batch file makes the passed or entered folder temporarily the current folder for the remaining commands using PUSHD and POPD instead of CD to work also with UNC paths.
There is checked next if the folder contains any file at all. Otherwise the user is informed that the directory does not contain files to archive and batch file ends without any further action.
The file movement is done with ROBOCOPY for the reasons described in a remark in the batch file which requires Windows Vista or a newer Windows version or Windows Server 2003 or a newer Windows server version.
I recommend to see also:
Debugging a batch file which answers your question.
What is the reason for "X is not recognized as an internal or external command, operable program or batch file"? It explains why path as name for the environment variable to assign the user entered path is a really bad idea.
How to stop Windows command interpreter from quitting batch file execution on an incorrect user input? It explains the reasons for using the additional code to evaluate the string entered by the user.
Why is no string output with 'echo %var%' after using 'set var = text' on command line? It explains the recommended syntax for the (re)definition of an environment variable and why using this syntax.
Syntax error in one of two almost-identical batch scripts: ")" cannot be processed syntactically here describes several common issues made by beginners in batch file coding like not enclosing a file/folder path in double quotes.
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 %~nx0, %~dp0 and %~1 whereby argument 0 is always the batch file itself.
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
md /?
pause /?
popd /?
pushd /?
rem /?
robocopy /?
set /?
setlocal /?
Other useful documentations used to write this code:
single line with multiple commands using Windows batch file
the Microsoft documentations for the used Windows Commands
the SS64 documentations for the used Windows CMD commands, especially:
ROBOCOPY.exe
ROBOCOPY Exit Codes
the Microsoft documentation about Using command redirection operators
and the SS64 documentation How-to: Redirection
Note: 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 with %ComSpec% /c and the command line within ' appended as additional arguments.

How to find and select newest file in a directory and restore with SQLRestore?

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

How to create folder based on first and second part of file name and move files into the folder?

I created the following batch script to create a folder based on today's date and then group files into folders based on the file name.
For example the files
JIM_BRICKMAN_QPS.avi
JIM_BRICKMAN_Slice.avi
JIM_BRICKMAN_Slice.jpg
are moved to the folder BRICKMAN.
This works fine, however, attempts to modify the batch file to move the newly created folders into the newly created date folder fail or overwrite the folders when going through the loop.
for /F "tokens=1-4 delims=/" %%A in ('date /t') do (
set DateDay=%%A
set DateMonth=%%B
set DateYear=%%C
)
set CurrentDate=%DateDay%-%DateMonth%-%DateYear%
if not exist "%CurrentDate%" md %CurrentDate%
for %%A in (*.avi *.jpg) do (
for /f "tokens=1,* delims=_" %%D in ("%%~nA") do (
md "%%D" 2>nul
echo Moving file %%A to folder %%D
move "%%A" "%%D" >nul
)
)
echo Finished
Additionally, I can't seem to get the token to ignore the first delimiter so that the folder is titled JIM_BRICKMAN and not just BRICKMAN.
EDIT:
I rewrote the batch file after the suggestions in the comments:
set "CurrentDate=%DATE:~-10,2%-%DATE:~-7,2%-%DATE:~-4%"
if not exist "%CurrentDate%" md %CurrentDate%
for %%A in (*.avi *.jpg) do (
for /f "tokens=1,2 delims=_" %%D_%%E in ("%%~nA") do (
md "%%D_%%E" 2>nul
move "%%A" "%%D_%%E" >nul
)
)
But the script seems to bomb out. I tried to capture the error, but it closes despite me putting PAUSE in the script.
Double clicking on a batch file in development is no good idea because this results in starting
%SystemRoot%\System32\cmd.exe /c "batch file name with full path and extension"
As it can be read on running cmd /? from within a command prompt window, the option /C means close the command process and its console window immediately after execution of command, executable or script finished independent on the reason for ending the execution.
For debugging a batch file in development it is much better to
open a command prompt window,
change the current directory with command CD to directory of batch file and
run the batch file by typing its name and hitting key RETURN or ENTER.
For batch files which should work independent on which directory is the current directory, it is advisable to omit point 2 and run the batch file with entering its full path, file name and file extension enclosed in double quotes with current directory being not the directory of the batch file.
A batch file is executed from within a command prompt window with:
%SystemRoot%\System32\cmd.exe /K BatchFileNameAsTyped
The option /K means keep command process running which results in keeping also command prompt window opened after execution of command/executable/script which makes it possible to read error messages.
The keys UP ARROW and DOWN ARROW can be used to reload command lines once entered in command prompt window making it easy to run the batch file once again after making a modification in GUI text editor.
And with having #echo off removed from first line of batch file, or changed to #echo ON, or commented out this line with command REM or with :: (invalid label) at beginning, it is also possible to see which lines Windows command interpreter really executes after applying immediate environment variable expansion and where an error occurs in case of a syntax error.
Wrong on second batch code is the line:
for /f "tokens=1,2 delims=_" %%D_%%E in ("%%~nA") do (
Specified as loop variable must be always 1 character. Right would be:
for /f "tokens=1,2 delims=_" %%D in ("%%~nA") do (
The command echo %DATE% outputs on my computer with my account and my region settings today the date 01.04.2017.
The command echo %DATE:~-10,2%-%DATE:~-7,2%-%DATE:~-4% outputs 01-04-2017.
So this part of the script works.
Hint: A list of directories in format YYYY-MM-DD is better than in format DD-MM-YYYY. The list of directories with format YYYY-MM-DD sorted alphabetically as by default is automatically with this date format also sorted from oldest to newest. Date format DD-MM-YYYY results in a weird list of the directories on being sorted alphabetically as by default.
A batch file for this task could be:
#echo off
set "CurrentDate=%DATE:~-10,2%-%DATE:~-7,2%-%DATE:~-4%"
for %%A in (*.avi *.jpg) do (
for /F "tokens=1,2 delims=_" %%D in ("%%~nA") do (
if not "%%E" == "" (
md "%CurrentDate%\%%D_%%E" 2>nul
move /Y "%%A" "%CurrentDate%\%%D_%%E\"
) else (
md "%CurrentDate%\%%D" 2>nul
move /Y "%%A" "%CurrentDate%\%%D\"
)
)
)
set "CurrentDate="
How the inner loop works is most interesting for this task.
for /F and "%%~nA" means the command FOR should process just the file name of the *.avi or *.jpg file without file extension found by outer FOR loop.
delims=_ means the FOR command should split up the string into multiple parts (tokens) using underscore as delimiter. The first file name is JIM_BRICKMAN_QPS which would be split up to:
JIM assigned to loop variable D being specified in FOR command line,
BRICKMAN assigned to loop variable E which is the next character in ASCII table after D and
QPS assigned to loop variable F.
This string split feature is the reason why loop variables are interpreted case-sensitive while environment variables are interpreted not case-sensitive.
With tokens=1,2 is specified that just first and second string parts are of interest. So inner FOR can stop string splitting after having already determined the first two underscore delimited strings and having assigned them to the loop variables D and E.
FOR executes the command block if it could determine at least 1 string delimited by an underscore. So it is possible that loop variable D has a string value, but loop variable E is an empty string, for example if the file name does not contain any underscore. That is the reason for the IF condition.
The command MD creates with command extensions enabled as by default the entire directory tree. Therefore it is not necessary to create the date subdirectory explicitly before searching for *.avi and *.jpg files. That is good as it avoids creating empty date directories when there are no *.avi and *.jpg files in current directory.
As the *.avi and *.jpg files in current directory should be moved to DD-MM-YYYY\Token1_Token2 it is of course necessary to specify also the environment variable with todays date string on creating the directory and moving the file.
The error message output by MD if the directory exists (or when it fails to create the directory because of missing permissions) to handle STDERR is redirected with 2>nul to device NUL to suppress it.
The MOVE command is used with option /Y to move the file to target folder even if the current file exists already in target folder.
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.
echo /?
for /?
if /?
md /?
move /?
set /?
Read also the Microsoft article about Using Command Redirection Operators.

Getting the attributes of the last modified file in a directory written in a file

I am in the need of a batch script that checks a drive (D:) for the 'last modified' attribute of *.czi files (Carl Zeiss image files) and append the data to a file on another drive. I have tried solutions with the following line:
FOR /F "delims=" %%I IN ('DIR %source%*.czi /A:-D /O:-D /T:W /B') DO COPY "%%I" > %target%
that does give me the last file, but it copies the entire file which is not that smart since they can be big. As a biologist I will spare you for my desperate attempts that did not work (spent 4-5 hours). I figure this can be done dead easily, that is if you know how... Any good suggestions? Any reply will be appreciated! Thanks in advance.
Let's assume just the last modified file time from newest file is wanted from all *.czi files in directory C:\Temp containing for example:
30.01.2017 08:13 First Listed.czi
28.01.2017 21:26 Oldest Image.czi
03.02.2017 17:13 Newest Image.czi
The batch code for this task could be:
#echo off
set "Source=C:\Temp\"
set "Target=%Source%List.txt"
for /F "delims=" %%I in ('dir "%Source%*.czi" /A:-D /B /O:-D /T:W 2^>nul') do (
echo File "%%I" last modified on %%~tI>>"%Target%"
goto AfterLoop
)
:AfterLoop
The command DIR searches in for *.czi files in directory C:\Temp and outputs the list sorted by last modification time in reverse order from newest to oldest.
In case of no *.czi file could be found, command DIR would output an error message to handle STDERR. This output message is redirected with 2>nul to device NUL to suppress it whereby the redirection operator > must be escaped here with ^ to be interpreted as redirection operator on execution of DIR command line and not already on parsing FOR command line.
%%I references the name of the file as output by DIR and %%~tI references the last modification date of the file. The help of command FOR output by running in a command prompt window for /? explains those modifiers.
The loop is exited after first output of the text redirected to the target file on which the line is appended if it is already existing because of using >> instead of just >.
For the example files list the following line is appended to C:\Temp\List.txt:
File "Newest Image.czi" last modified on 03.02.2017 17:13
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 /?
echo /?
for /?
goto /?
set /?
See also the Microsoft article Using command redirection operators.
Your question is unclear, so let me try to rephrase it:
I think you want to find the Most Recently Modified file with a .CZI extension, and copy only that newest file to some target destination.
To list all .CZI files in all subdirectories, sorted by newest-file first:
(for /f %a in ('dir *.CZI /s /b') do #echo %~ta %~fa) | sort
If the first line of this output is the file that you want, then all you need to do is copy that one file to your target.
(and please, take the time to write detailed and clear questions so we can provide good answers)

Batch File to Move Files based on List of Strings

I have searched for days with results of similar circumstances but none that exactly addresses my problem.
Problem: I have 10,000 files in C:\Data folder. They all have a file name such as 1234_File_Log_Date_Time.csv. 1234 is a serial number. I have a list of multiple serial in a SN.txt file. I would like to have a batch file read SN.txt, then copy the files found in C:\Test Data based on this list to another directory of C:\My Data. There are no duplicate files to contend with.
I have never written a batch file in my life so be gentle haha.
I have never written a batch file in my life... Read Command-Line Reference or Windows Commands.
For an initial look, start with a simple batch script which could appear like
#ECHO OFF >NUL
SETLOCAL EnableExtensions
pushd "C:\Data"
for /f "delims=" %%G in (SN.txt) do (
echo "%%~G"
)
popd
pause
Then replace the echo "%%~G" line (step by step) with
if exist "%%~G_*.csv" dir /B "%%~G_*.csv" (to see file names that are to be copied);
if exist "%%~G_*.csv" echo copy /B "%%~G_*.csv" "C:\My Data\" (to see commands that are to be performed);
if exist "%%~G_*.csv" copy /B "%%~G_*.csv" "C:\My Data\" (final edit to execute the commands).
Additional resources (required reading for any batch scripter):
(command reference) An A-Z Index of the Windows CMD command line
(additional particularities) Windows CMD Shell Command Line Syntax
(%~G etc. special page) Command Line arguments (Parameters)
(special page) EnableDelayedExpansion

Resources