Batch if file not exist create else rename - batch-file

if not defined filename set filename=123.txt
if not defined folder set folder=January
set BASE_DIR=C:\Users\xxx\Desktop\
set file=%BASE_DIR%%folder%\%filename%
I am having difficult time coming with algorithma to accomplish what I am trying to do.
Every time this batch script runs filename and foldercan be different.
I am trying to check if file exist if it does no need to do
anything goto end.
If file does NOT exist and there is a another file under that folder. I need to update that filename with given.
However, there might be case where I wouldnt even have folder exist.
In that case I need to make folder and file inside of that folder.
Content inside file is always empty.
I dont need code, I just need help with logic to accomplish this.

This commented batch file should be helpful for you to finish your batch file coding task:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
if not defined FileName set "FileName=123.txt"
if not defined Folder set "Folder=January"
set "BASE_DIR=%UserProfile%\Desktop"
set "FilePath=%BASE_DIR%\%Folder%"
set "FullFileName=%FilePath%\%FileName%"
rem Exit batch file execution if file already exists.
if exist "%FullFileName%" goto :EOF
rem Create the entire directory structure for the file if directory
rem does not already exist. Note the backslash at end which prevents
rem condition evaluating to true if a file with name "%Folder%"
rem exists in "%BASE_DIR%".
if not exist "%FilePath%\" md "%FilePath%" 2>nul
rem The creation of the directory tree could fail for various reasons.
if not exist "%FilePath%\" (
echo Error by %~f0:
echo/
echo Directory "%FilePath%" could not be created.
echo/
pause
goto :EOF
)
rem Add here more code to create/copy/move file "%FileName%" in/to "%FilePath%".
rem For example creating an empty file:
type NUL >"%FullFileName%"
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 /?
endlocal /? ... not explicitly used here. cmd.exe automatically restores previous environment on terminating batch file execution. See this answer for details about the commands SETLOCAL and ENDLOCAL.
goto /?
if /?
md /?
rem /?
set /?
setlocal /?
type /?
See also:
Where does GOTO :EOF return to?
How to create empty text file from a batch file?
Microsoft's command-line reference
SS64.com - A-Z index of the Windows CMD command line
Wikipedia article about Windows Environment Variables for environment variable UserProfile.

Related

How to insert a line into a text file after the first line?

I play Fallout 4 VR with Mod Organizer 2 (mo2), and most mods require
*Fallout4_VR.esm
at the top of the file plugins.txt, but mo2 keeps removing it.
So I downloaded a batch file which adds that line at the top of the file on execution.
But the problem is that mo2 has this at the top:
# This file was automatically generated by Mod Organizer.
*DLCRobot.esm
*DLCworks...
etc.
This is the code in the batch file:
#echo off
cls
setlocal enabledelayedexpansion
TITLE FO4VR Launch Codes
REM Find plugins.txt
set "file=C:\Modding\MO2\profiles\Default\plugins.txt"
if not exist "%file%" (
echo ERROR - Could not find %file%
echo.
goto FAIL
) else (
findstr /b /l /i /n "*Fallout4_VR.esm" %file%
if !errorlevel! == 0 (
echo VR ESM entry already exists. Good to go.
echo.
) else (
REM needs to add
(echo *Fallout4_VR.esm) >plugins.txt.new
type %file% >>plugins.txt.new
move /y plugins.txt.new %file%
echo VR ESM entry prepended to %file%.
echo.
)
)
echo.
pause
What do I need to edit so *Fallout4_VR.esm is below the whole line with generated by Mod Organizer instead of top of the file?
The file plugins.txt should be finally:
# This file was automatically generated by Mod Organizer.
*Fallout4_VR.esm
*DLCRobot.esm
*DLCworks...
etc.
The task to add at top the line with *Fallout4_VR.esm to contents of the file plugins.txt below the comment line(s) could be done with the following code:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
cls
title FO4VR Launch Codes
rem Find plugins.txt
set "PluginsFile=C:\Modding\MO2\profiles\Default\plugins.txt"
rem Use the line below instead of the line above if the file
rem plugins.txt is always in the same directory as the batch file.
rem set "PluginsFile=%~dp0plugins.txt"
if not exist "%PluginsFile%" echo ERROR: Could not find: "%PluginsFile%"& goto EndBatch
%SystemRoot%\System32\findstr.exe /B /I /L /C:"*Fallout4_VR.esm" "%PluginsFile%" >nul
if not errorlevel 1 echo VR ESM entry already exists. Good to go.& goto EndBatch
set "LineInsert=1"
(for /F usebackq^ delims^=^ eol^= %%I in ("%PluginsFile%") do (
if defined LineInsert (
set "CommentLine=1"
for /F "eol=#" %%J in ("%%~I") do set "CommentLine="
if not defined CommentLine (
echo *Fallout4_VR.esm
set "LineInsert="
)
echo(%%I
) else echo(%%I
))>"%PluginsFile%.tmp"
if not exist "%PluginsFile%.tmp" echo ERROR: Could not create temporary file: "%PluginsFile%.tmp"& goto EndBatch
%SystemRoot%\System32\attrib.exe -r "%PluginsFile%"
move /Y "%PluginsFile%.tmp" "%PluginsFile%" >nul 2>nul
if not errorlevel 1 echo VR ESM entry added to: "%PluginsFile%"& goto EndBatch
del "%PluginsFile%.tmp"
echo ERROR: Could not update: "%PluginsFile%"
:EndBatch
echo/
if /I not "%~1" == "/N" pause
endlocal
ATTENTION: The result is only correct if
plugins.txt is not a Unicode encoded text file with encoding UTF-16
and has DOS/Windows line endings (carriage return + line-feed).
It is advisable to avoid command blocks starting with ( and ending with a matching ) because that makes it possible to do the task without usage of delayed variable expansion and therefore the batch file works also with plugins.txt stored in a directory with a path like C:\Temp\Development & Test(!) 100%. It is of course necessary to use command blocks for the for /F loop processing the lines in the text file to modify.
The outer FOR loop processes the lines in the text file with skipping empty lines and assigning each non-empty line completely to the specified loop variable I. The option usebackq instructs FOR to interpret the string in double quotes as file name of which lines to process and not as string to process. The option delims= defines an empty list of delimiters to prevent splitting the lines up on normal spaces and horizontal tabs. The option eol= defines no character as end of line character. The unusual syntax without " around the three options must be used in this special case which requires escaping the spaces and the equal signs with caret character ^ to get usebackq delims= eol= interpreted as one argument string with the three options for command FOR.
The first IF condition is true as long as the line with *Fallout4_VR.esm is not output. In this case there is first defined the environment variable CommentLine with a value whereby the value itself does not matter.
The inner for /F processes the current line as string with ignoring the line on starting with # after zero or more leading spaces/tabs. So if the current line is a comment line, the environment variable CommentLine is still defined after execution of the inner for /F while this environment variable is deleted on current line is not a comment line.
If the current line is not a comment line, there is output *Fallout4_VR.esm to insert that as line into the temporary file and the environment variable LineInsert is deleted before next is output in any case the current line.
All other lines of the text file are just output after inserting the line with *Fallout4_VR.esm detected by environment variable InsertLine no longer existing.
Everything output during execution of the outer FOR loop is written by cmd.exe into a temporary file in same directory as the text file to update which should work as long as the directory is not write-protected for the user or there is already a directory with the name of the temporary file (very unlikely) or a read-only file with that name (also very unlikely).
The read-only file attribute is removed from the file to update if it would have the read-only file attribute set.
Next the temporary file is moved over the existing file to update which can fail like on write access to file is denied because of the file is currently opened by an application which denies the shared file write access.
The batch file can be started with the option /N to avoid the user prompt with command pause at end of the batch file.
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 /? ... for %~dp0 ... drive and path of argument 0 ... batch file path
cls /?
copy /?
del /?
echo /?
endlocal /?
findstr /?
for /?
goto /?
if /?
move /?
pause /?
rem /?
set /?
setlocal /?
title /?
See also:
DosTips forum topic: ECHO. FAILS to give text or blank line - Instead use ECHO/
Microsoft documentation about Using command redirection operators
Single line with multiple commands using Windows batch file

What is the reason for error message "N was unexpected at this time"?

File: stack.bat
#echo off
#setlocal enabledelayedexpansion
for %%a in (%*) do (
call set "%%~1=%%~2"
shift
)
ECHO para1 %--para1%
ECHO para2 %--para2%
if "%--para2%"=="" (
echo missing para2
for /f "eol=: delims=" %F in ('dir /b/o:N %--folder%\*.001') do #set "newest=%F"
echo latest %newest%
)
This batch file is called with:
stack.bat --para1 c:\Sample\temp
The execution results in output of the error message:
N was unexpected at this time.
There is no error if the line for /f "eol=: ... is commented out with command REM.
Delayed expansion is already enabled.
What do I need to do to fix the error?
It is not described what the batch file code should do at all. It looks like it should find the newest file by its name containing most likely a date string in name in a directory passed as argument to the batch file and should define an environment variable with name passed also as argument left to the directory path with the file name of newest file.
I suggest following commented batch code for this purpose:
#echo off
rem Remove this line if the environment variables defined by this batch
rem file should still exist after processing of this batch file finished.
setlocal EnableExtensions DisableDelayedExpansion
rem Delete all environment variables of which name starts with --.
for /F "delims=" %%I in ('set -- 2^>nul') do set "%%I"
:ProcessArguments
rem Get current first argument (option) with surrounding " removed.
set "Option=%~1"
rem Is there no more option?
if not defined Option goto EndBatch
rem Remove all double quotes from the option.
set "Option=%Option:"=%"
rem This condition is just for 100% fail safe code. It should be never true.
if not defined Option goto EndBatch
rem Does the option not start with two hyphens?
if not "%Option:~0,2%" == "--" (
echo ERROR: Invalid option: "%Option%"
echo/
goto EndBatch
)
rem Get current second argument (folder path) with surrounding " removed.
set "Folder=%~2"
rem Is there no folder path?
if not defined Folder goto MissingFolder
rem Remove all double quotes from the folder path.
set "Folder=%Folder:"=%"
rem This condition is just for 100% fail safe code. It should be never true.
if not defined Folder goto MissingFolder
rem Replace all / in folder path by \ as many users type folder paths wrong
rem with slashes as on Linux/Mac instead of backslashes as required on Windows.
set "Folder=%Folder:/=\%"
rem Make sure the last character of folder path is a backslash.
if not "%Folder:~-1%" == "\" set "Folder=%Folder%\"
rem Search in specified folder for *.001 files output reverse by name and
rem define the option as environment variable with first output file name
rem assigned with full qualified absolute path even if environment variable
rem Folder referencing a relative path. Then shift the arguments list by
rem two arguments to the left and process the remaining arguments.
for /F "eol=| delims=" %%I in ('dir "%Folder%*.001" /A-D /B /O-N 2^>nul') do (
for %%J in ("%Folder%%%I") do set "%Option%=%%~fJ"
shift
shift
goto ProcessArguments
)
rem It is not possible to define an environment variable with no string.
rem So an error message is output if no file could be found like on
rem wrong folder path or no *.001 file found in the specified folder.
echo ERROR: Could not find a *.001 file for option "%Option%" in folder:
echo "%Folder%"
echo/
goto Endbatch
:MissingFolder
echo ERROR: Missing folder path for option: "%Option%"
echo/
:EndBatch
set "Option="
set "Folder="
echo Options parsed successfully:
echo/
set -- 2>nul
rem Remove this line if the environment variables defined by this batch
rem file should still exist after processing of this batch file finished.
endlocal
This batch file can be started for example with the command line:
stack.bat --para1 c:\Sample\temp "--para2" "C:/Temp/Development & Test!/" --para3 . --para4 "\Program Files\Internet Explorer\" -para5 .."
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 how to reference batch file arguments
dir /?
echo /?
endlocal /?
for /?
goto /?
if /?
rem /?
set /?
setlocal /?
shift /?
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 with %ComSpec% /c and the command line within ' appended as additional arguments.
I suggest also reading:
How does the Windows Command Interpreter (CMD.EXE) parse scripts?
This question with its answers should be read first by every beginner in batch file coding.
Problems checking if string is quoted and adding quotes to string
This answer explains very detailed how to process arguments passed to a batch file.
Syntax error in one of two almost-identical batch scripts: ")" cannot be processed syntactically here
This answer describes common issues made by beginners in batch file coding and how to avoid them.
Why is no string output with 'echo %var%' after using 'set var = text' on command line?
Another extensive answer which describes how to work with environment variables in batch files.
Symbol equivalent to NEQ, LSS, GTR, etc. in Windows batch files
This also very long answer describes in detail how a string comparison is done by Windows command processor and what a batch file writer must take into account on using string comparisons.

How to save a variable to a batch file?

This is my code:
set /p name=user save name
if %name%==[""]
cd c:\users\student\desktop\login system\usersXD
echo set "name=%name%"> %name%.bat
My code is not working. and i will like to load them up to view
I suggest following code for this task:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
goto PromptName
:ErrorInvalid
echo/
echo Error: The character !InvalidChar! is not allowed in name.
echo/
endlocal
:PromptName
set "Name="
set /P "Name=User save name: "
rem Has the user not input anything?
if not defined Name goto PromptName
rem Remove all double quotes from input string.
set "Name=%Name:"=%"
rem Has the user input just double quotes?
if not defined Name goto PromptName
rem Check if the input string contains any character not allowed in a file name.
setlocal EnableDelayedExpansion
for %%I in ("<" ">" ":" "/" "\" "|") do if not "!Name:%%~I=!" == "!Name!" set "InvalidChar=%%~I" & goto ErrorInvalid
if not "!Name:?=!" == "!Name!" set "InvalidChar=?" & goto ErrorInvalid
if not "!Name:**=!" == "!Name!" set "InvalidChar=*" & goto ErrorInvalid
endlocal
cd /D "%UserProfile%\Desktop\login system\usersXD"
echo set "Name=%Name%">"%Name%.bat"
endlocal
The file name of the batch file to create must be enclosed in double quotes because it could contain a space or one of these characters &()[]{}^=;!'+,`~ which require enclosing the file name in double quotes.
This batch file should not be stored in directory %UserProfile%\Desktop\login system\usersXD on having file extension .bat as it could be overwritten during execution if the user enters a name the name of the batch file. It would be safe to have this batch file in that directory with file extension .cmd.
The batch file is still not 100% fail-safe despite the checks already added, but the user input string itself cannot result anymore in an exit of batch file execution because of a syntax error.
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 /?
echo /?
endlocal /?
for /?
goto /?
if /?
rem /?
set /?
setlocal /?
See also:
Wikipedia article listing the predefined Windows environment variables like UserProfile
Single line with multiple commands using Windows batch file explaining the operator &
How to stop Windows command interpreter from quitting batch file execution on an incorrect user input?
Microsoft documentation page Using command redirection operators explaining the redirection operator >
Microsoft documentation page Naming Files, Paths, and Namespaces listing which characters are not allowed in file/folder names
This should work to save a variable in a bat file
If I remember
(
Echo set test=%
Echo set test=%test%
Echo set test=%test%
)>Test.bat

How to create file numeration on moving files to a directory?

I use the commands below to rename files and move them to a directory:
ren credentials* passwords%random%.txt
move E:/passwords*.txt E:/Passwords/
The file rename puts a random number like 1231 or something like this into new file name.
So I can identify it respectively no existing file is overwritten. But that is not the subject.
What I want to know is: How could I make a file numeration?
I would like to have the credentials* files in current directory moved to the passwords directory with passwordsX.txt as new file name whereby X should be the next free number according to existing passwords*.txt files.
So if there are already passwords1.txt and passwords2.txt in the passwords directory, the file credentialsX should be moved to the passwords directory with new name passwords3.txt and credentialsY as passwords4.txt.
Here is a comment batch file for this task asked and answered already often on Stack Overflow.
#echo off
if not exist "credentials*" goto :EOF
setlocal EnableExtensions DisableDelayedExpansion
set "NextNumber=0"
for %%I in (E:\Passwords\passwords*.txt) do call :GetHighestNumber "%%~nI"
for %%I in (credentials*) do call :MoveFile "%%I"
endlocal
goto :EOF
rem GetHighestNumber is a subroutine which must be called with a passwords*
rem file name without file extension. It determines the number of the current
rem passwords file and compares it with currently highest file number to get
rem finally the currently highest number in all existing passwords*.txt files.
:GetHighestNumber
set "FileName=%~1"
rem Get from file name without file extension the characters after passwords.
set "FileNumber=%FileName:~9%"
rem Ignore the file passwords.txt if existing by chance.
if not defined FileNumber goto :EOF
rem Delete the environment variable FileNumber if it contains any other
rem character than digits to ignore files like passwords12_bak.txt.
for /F "delims=0123456789" %%N in ("%FileNumber%") do set "FileNumber="
rem Has the passwords*.txt file a different string matched by wildcard *
rem than a decimal number, ignore this file and exit this subroutine.
if not defined FileNumber goto :EOF
rem Remove leading zeros to avoid getting the decimal number
rem interpreted as octal number on integer comparison below.
:RemoveLeading0
if not "%FileNumber:~0,1%" == "0" goto CompareNumbers
set "FileNumber=%FileNumber:~1%"
if defined FileNumber goto RemoveLeading0
set "FileNumber=0"
rem The number could be greater than 2147483647 in which case
rem the integer comparison would be not correct because Windows
rem command interpreter does not support larger values.
:CompareNumbers
if %FileNumber% GTR %NextNumber% set "NextNumber=%FileNumber%"
goto :EOF
rem Subroutine MoveFile increases the next file number by 1 and
rem moves the credentials* file to E:\Passwords\passwords*.txt
rem with the incremented file number in file name.
:MoveFile
set /A NextNumber+=1
move %1 "E:\Passwords\passwords%NextNumber%.txt"
goto :EOF
Please note that on Windows the directory separator is \ and not / as on Unix/Linux/Mac. / is used on Windows usually as begin of a parameter as it can be seen on the batch code above while on Unix/Linux/Mac - is used usually as begin of a parameter.
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 /?
echo /?
endlocal /?
for /?
goto /?
if /?
move /?
rem /?
set /?
setlocal /?
Read also Where does GOTO :EOF return to? and this answer for details about the commands SETLOCAL and ENDLOCAL.

How to rename all files within a folder not starting with a specific prefix string?

I have a folder which contains for example the following files:
RAW_123432542_343.text
231453254_213.text
RAW_324324_32432423.text
32432423_4543.text
What I need is renaming all files which do not have RAW_ as prefix. The folder has thousands of files.
How to rename all files within the folder not starting with RAW_?
This could be done for example with following batch code:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
for %%I in ("C:\Temp\*.text") do (
set "FileName=%%~nI"
if /I not "!FileName:~0,4!" == "RAW_" ren "%%~I" "RAW_%%~nxI"
)
endlocal
If a string is assigned to an environment variable within a code block starting with ( and ending with a matching ) and referencing the string or parts of the string of this environment variable within same code block is necessary as for this rename operation, delayed expansion must be used as shown above. The help of command set explains this on a simple IF and a simple FOR example very clear.
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 /?
endlocal /?
for /?
if /?
ren /?
set /?
setlocal /?

Resources