I'm creating then zipping a file that is stamped with the current date with 7-zip. I am able to use the following switch to create the zip file to add to:
7z -tzi C:\RACHAEL\my_work\dbs\MyDb\%DATE:~11,4%\%DATE:~5,2%\MyDb_bak_%DATE:~11,4%-%DATE:~5,2%-%DATE:~8,2%.bak.zip
but adding the "-i!" command does not locate the file specfied
7z -tzi C:\RACHAEL\my_work\dbs\MyDb\%DATE:~11,4%\%DATE:~5,2%\MyDb_bak_%DATE:~11,4%-%DATE:~5,2%-%DATE:~8,2%.bak.zip -i!C:\RACHAEL\my_work\dbs\MyDb_bak_<get_current_date_in_correct_format>.bak
How would one achieve locating the file in this directory containing the current formatted date from a batch file? Is there an escape character? The '%' does not provide this purpose in 7zip, which I assumed it would.
Thanks in advance!
forfiles /d +0 /c "cmd /c echo #path"
See forfiles /?
Format of date string of environment variable DATE depends on language settings of Windows.
Executing a batch file with the 2 lines below on German Windows XP
#echo %DATE%
#echo %DATE:~6,4%-%DATE:~5,2%-%DATE:~8,2%
results in output
16.08.2014
-.2-14
This is not a valid date string in format YYYY-MM-DD as you want obviously in your command.
I needed to change the second line to
#echo %DATE:~6,4%-%DATE:~3,2%-%DATE:~0,2%
to get output on running the batch file in a command prompt window
16.08.2014
2014-08-16
Explanation for above date string with substring extraction:
%DATE:~6,4% ... extracts from string of environment variable DATE four characters beginning from seventh character. First character has character index 0.
%DATE:~3,2% ... extracts from string of environment variable DATE two characters beginning from fourth character.
%DATE:~0,2% ... extracts from string of environment variable DATE two characters beginning from first character.
Now you know what the date substring extraction code in your commands do. And you can see also how to verify output of substring extraction code using a small batch file executed from within a command prompt window, or from Windows Explorer after appending a third line with command pause to see the output.
This should help you to find the correct code for date string building on your computer according to requested date format depending on date string format of environment variable DATE.
Character ! has a special meaning in batch files as it is used for referencing the value of an environment variable with delayed expansion. To get it interpreted as literal character in a batch file, it must be escaped with ^ which means putting left to ! the character ^ resulting in ^!.
Therefore the command
7z.exe a -tzip C:\RACHAEL\my_work\dbs\MyDb\%DATE:~11,4%\%DATE:~5,2%\MyDb_bak_%DATE:~11,4%-%DATE:~5,2%-%DATE:~8,2%.bak.zip -i^!C:\RACHAEL\my_work\dbs\MyDb_bak_%DATE:~11,4%-%DATE:~5,2%-%DATE:~8,2%.bak
might the right one in a batch file on your computer.
But on German Windows XP the right command is:
7z.exe a -tzip C:\RACHAEL\my_work\dbs\MyDb\%DATE:~6,4%\%DATE:~3,2%\MyDb_bak_%DATE:~6,4%-%DATE:~3,2%-%DATE:~0,2%.bak.zip -i^!C:\RACHAEL\my_work\dbs\MyDb_bak_%DATE:~6,4%-%DATE:~3,2%-%DATE:~0,2%.bak
One laste note: In batch file it is often better to specify executables with full path. Therefore it is better here to specify not just 7x.exe, but something like "C:\Program Files\7-Zip\7z.exe". The path to 7x.exe may be different on your computer.
was missing the escape character ^ before the path I was trying to add to the successfully zipped directory created with 7zip.
This is the corrected statement:
echo Using 7-zip to compress today's backup folder...
7z a -tzip C:\RACHAEL\my_work\dbs\MyDb\%DATE:~11,4%\%DATE:~5,2%\MyDb_bak_%DATE:~11,4%-%DATE:~5,2%-%DATE:~8,2%.bak.zip -i!^C:\RACHAEL\my_work\dbs\MyDb\%DATE:~11,4%\%DATE:~5,2%\MyDb_bak_%DATE:~11,4%-%DATE:~5,2%-%DATE:~8,2%.bak
^missing escape character right here so that path could actually be parsed per date format.
Related
This is my Windows script which is started every x minutes:
cd C:\
cd Speedtest
speedtest.exe -s 18571 -f csv>>Speedtest.log
How to add a timestamp to every log line?
Let us assume the application speedtest runs just one test run on each execution and outputs one or more lines without empty lines and on each line the current time on starting this application should be written first into the CSV file with , as list separator (default in most countries for CSV files). In this case the following batch file could be used for this task:
#cd /D "C:\Speedtest" 2>nul && #for /F delims^=^ eol^= %%I in ('speedtest.exe -s 18571 -f csv') do >>"Speedtest.log" #echo %TIME%,%%I
The first command CD changes the current directory to C:\Speedtest. This command fails if the directory does not exist. The error message output on changing directory failed is redirected with 2>nul from handle STDERR (standard error) to device NUL to suppress it. There is nothing output by CD if the current directory could be successfully changed to the specified directory.
The operator && results in executing the next command FOR only if CD exited with 0 indicating a successful change of the current directory which means the specified directory C:\Speedtest really exists.
FOR with option /F and a set specified between two ' results in execution of one more command process in background with %ComSpec% /c and the strings between the two ' appended as further arguments. So executed is on Windows installed to C:\Windows:
C:\Windows\System32\cmd.exe /c speedtest.exe -s 18571 -f csv
The started Windows command process executes speedtest.exe with the four specified arguments and then closes itself because of option /c.
FOR captures all output written to handle STDOUT (standard output) and processes it after started cmd.exe terminated itself.
FOR ignores all empty lines on processing the captured lines.
FOR would split up by default each line into substrings using normal space and horizontal tab as string delimiters and would assign just first space/tab separated string of a non-empty line to specified loop variable I. This string splitting behavior is not wanted here. For that reason option delims= is used to define an empty list of string delimiters which disables line splitting behavior.
FOR would ignore by default all lines on which first substring starts with a semicolon because of eol=; is the default for end of line option. It is unknown if speedtest outputs the lines with a semicolon at beginning. For that reason the option eol= is used to define no end of line character which means all lines except empty lines are assigned completely to specified loop variable I.
The two options delims= and eol= are specified usually in a double quoted argument string to get the two equal signs and the space character between interpreted as literal characters and not as argument separators by Windows command processor. But "delims= eol=" cannot be used here as FOR would interpret in this case " as end of line character. Therefore the two options must be written without " which requires escaping the two equal signs and the space character with ^ to be interpreted as literal character instead of argument separators by Windows command processor.
Windows command processor parses the entire line before execution of command CD and replaces during this parsing process %TIME% by the current value of the local time in format defined by the country configured for the account used to run this batch file. So the time written into the CSV file is the time on which the entire command line was parsed by cmd.exe before executing the command CD and on success next the other commands and executables.
The redirection operator >> with the file name Speedtest.log is specified left to command ECHO to be 100% safe that the line is written correct into the file without a trailing space even on ending with number 1 to 9. It can be seen on running this batch file from within a command prompt window without the three # that cmd.exe moved >>"Speedtest.log" to end of the command line with inserting left to this string a space and 1 before executing command CD. It must be always taken into account how a command line looks like after processing it by Windows command processor before executing the command and not how it is written in the batch file.
Note: If the configured country is Germany, Austria, Switzerland, Luxembourg or Liechtenstein with time format HH:mm:ss,ms and list separator ;, it is necessary to use a semicolon instead of a comma between %TIME% and %%I to produce a valid CSV file. speedtest outputs the data in this case hopefully also with ; instead of ,. Otherwise if speedtest outputs the data independent on list separator of the configured country always with a comma, it would be necessary to use on command ECHO either "%TIME%",%%I or %TIME:,=.%,%%I to get a valid CSV file using comma as separator.
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 /?
for /?
set /?
See also:
How does the Windows Command Interpreter (CMD.EXE) parse scripts?
Single line with multiple commands using Windows batch file
Microsoft article about Using command redirection operators
I have the following batch file to make git diff invoke spreadsheet compare UI in windows. So I'm trying to pass the git diff's 2nd (old file) and 5th (new file) arguments to spreadsheet compare in order to make it compare the file using git diff.
So now, this batch file only successfully handles files with NO spaces in the file names, it CANNOT handle files with spaces in the file names.
What code should I add to this script to make this batch code handles file with spaces:
#ECHO OFF
set path2=%5
set path2=%path2:/=\%
ECHO %2 > tmp.txt
dir %path2% /B /S >> tmp.txt
C:/"Program Files"/"Microsoft Office"/root/vfs/ProgramFilesX86/"Microsoft Office"/Office16/DCF/SPREADSHEETCOMPARE.EXE tmp.txt
It currently throw errors like this:
Unhandled Exception: System.ArgumentException: Illegal characters in path.
at System.IO.Path.CheckInvalidPathChars(String path, Boolean checkAdditional)
at System.IO.Path.GetFileName(String path)
at ProdianceExcelCompare.Form1.StatusReady()
at ProdianceExcelCompare.Form1.Init()
at ProdianceExcelCompare.Form1..ctor(String instructionFile)
at ProdianceExcelCompare.Program.Main(String[] args)
fatal: external diff died, stopping at London comparison.xlsx
See the following answers on Stack Overflow:
How to set environment variables with spaces?
Why is no string output with 'echo %var%' after using 'set var = text' on command line?
They explain the recommended syntax set "VariableName=variable value" to define an environment variable and the reasons recommending this syntax.
Why does ECHO command print some extra trailing space into the file?
It explains why the space character left to redirection operator > on an ECHO command line is also written into the file as trailing space and how to avoid this safely on variable text written into the file.
See also Microsoft documentation about Using command redirection operators.
On other command lines than ECHO a space left to > is usually no problem.
It is in general wrong to use multiple times " within an argument string like a file or folder path. There should be just one " at beginning and one " at end. This is explained by help of Windows command processor output on last help page on running in a command prompt window cmd /?.
The Microsoft documentation about Naming Files, Paths, and Namespaces explains that the directory separator on Windows is \ and not / and therefore / should not be used in batch files on Windows in file/folder paths.
The help output on running in a command prompt window call /? explains how the arguments of a batch file can be referenced with which modifiers.
The code rewritten according to information posted above and on the referenced pages:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "path2=%~5"
set "path2=%path2:/=\%"
>"tmp.txt" echo %2
dir "%path2%" /B /S >>"tmp.txt" 2>nul
"%ProgramFiles%\Microsoft Office\root\vfs\ProgramFilesX86\Microsoft Office\Office16\DCF\SPREADSHEETCOMPARE.EXE" "tmp.txt"
endlocal
The first line in tmp.txt contains the second argument as passed to the batch file, i.e. without or with surrounding double quotes.
The following code is necessary to write the second argument safely always without " into file tmp.txt even on second argument passed to the batch file is "Hello & welcome!":
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "path2=%~5"
set "path2=%path2:/=\%"
set "Argument2=%~2"
setlocal EnableDelayedExpansion
echo !Argument2!>"tmp.txt"
endlocal
dir "%path2%" /B /S >>"tmp.txt" 2>nul
"%ProgramFiles%\Microsoft Office\root\vfs\ProgramFilesX86\Microsoft Office\Office16\DCF\SPREADSHEETCOMPARE.EXE" "tmp.txt"
endlocal
>tmp.txt echo %~2 cannot be used as not working for something like "Hello & welcome!". Windows command processor would interpret the first string separated by normal space, horizontal tab, comma, equal sign, or no-break space (in OEM code pages) delimited string after & as command or application to execute as described by single line with multiple commands using Windows batch file.
"tmp.txt" could be written everywhere in both batch files also with just tmp.txt. But it is never wrong to enclose the complete file/folder argument string in double quotes even on not being really necessary because of the string does not contain a space or one of these characters &()[]{}^=;!'+,`~. So it is good practice to always enclose a complete file/folder argument string in double quotes. For example running a replace on both batch files searching for tmp.txt and using as replace string %TEMP%\%~n0.tmp would result in using instead of tmp.txt in current directory a temporary file with name of batch file as file name and file extension .tmp in directory for temporary files independent on what is the name of the batch file and what is the path of the directory for temporary files.
The last suggestion is reading this answer for details about the commands SETLOCAL and ENDLOCAL.
The temporary file should be also deleted finally before reaching an exit point for batch file execution.
You can use quotes as below:
It treats the string in quotes as a title of the new command window. So, you may do the following:
start "" "yourpath"
Found it in the below link :
https://ccm.net/forum/affich-16973-open-a-file-with-spaces-from-batch-file
I have a bat file that does the following.
xcopy c:\folder\*.* d:\another_folder\.
del *.xml
del *.lst
The generated file has a timestamp in its name:
MY_FILE_11111_08-23-2016_111111.xml
The date time starts after the third _ formatted as MM-DD-YYYY_HHMMSS
How do I write a bat command that will only copy if the filename has today's date?
There is the predefined environment variable DATE which holds current local date in format defined by the Windows Region settings. Run in a command prompt window the line
echo %DATE%
In case of output is 08/23/2016 (MM/DD/YYYY) just each slash must be replaced in the string by a hyphen as wOxxOm suggested already with a one-liner command line.
set "FileDate=%DATE:/=-%"
%SystemRoot%\System32\xcopy.exe "C:\Folder\*%FileDate%*" "D:\Another_Folder\"
But current date string must be reformatted if output is for example Tue, 23/08/2016 (with weekday) or just 23/08/2016 (without weekday) which would be for both date format examples:
set "FileDate=%DATE:~-7,2%-%DATE:~-10,2%-%DATE:~-4%"
%SystemRoot%\System32\xcopy.exe "C:\Folder\*%FileDate%*" "D:\Another_Folder\"
How the character replace (first method) respectively concatenation of specific substrings (second method) works is explained in help of command SET which can be read by opening a command prompt window and running set /? or alternatively help set.
If just a single file must be copied, it is most likely enough to use internal command COPY of Windows command processor instead of Windows standard console application (external command) xcopy.exe. Run in a command prompt window copy /? and xcopy /? to get displayed the helps for those two copying commands.
I'm building a script for Windows command line in which I try to check some filenames in a FOR loop, and then stripping off part of the filename into a variable for further use. Basically, what I want to happen is this:
List all files in a certain directory, splitting of the extension like .osm.pbf in this case.
Assign the filename to a variable.
Out the last 7 characters of the filename in another variable.
Compare this new variable to "-latest".
If the compare is true, cut a part of the variable containing the filename.
If the compare is false, take over the complete variable into another variable.
Through some trial and error and some searching online, I've arrived at this point (which still isn't doing what I want):
FOR /F "tokens=1-2 delims=." %%M IN ('DIR /b %VECTOR_WORKDIR%\*.osm.pbf') DO (
SET VECTOR_CURRENT_MAP2=%%M
ECHO !VECTOR_CURRENT_MAP2! >> %VECTOR_LOGFILE%
SET LAST_BIT_TEMP=!VECTOR_CURRENT_MAP2:~-7!
ECHO !LAST_BIT_TEMP! >> %VECTOR_LOGFILE%
SET LAST_BIT=!LAST_BIT_TEMP: =!
ECHO !LAST_BIT! >> %VECTOR_LOGFILE%
IF !LAST_BIT!=="-latest" (
SET VECTOR_CURRENT_MAP3=!VECTOR_CURRENT_MAP2:~0,-8!
ELSE
SET VECTOR_CURRENT_MAP3=!VECTOR_CURRENT_MAP2!
)
ECHO !VECTOR_CURRENT_MAP3! >> %VECTOR_LOGFILE%
)
This results in these lines in the log file, for the file basse-normandie-latest.osm.pbf:
basse-normandie-latest
-latest
-latest
ECHO is on.
The first echo is correct, although the filename has a trailing space. (So actually it's "basse-normandie-latest ".)
The second echo doesn't seem to take this training space into account, as it correctly gives "-latest" as the last 7 characters. This echo also has a trailing space (So actually it's "-latest ".)
The third echo is an attempt to clear the spaces from the variable (by using ": ="), but this results in another trailing space. (So actually it's "latest ".)
The final echo after the IF statement (where I try to cut the "-latest" part from the filename), results in "ECHO is on".
I have SETLOCAL enabledelayedexpansion enableextensions declared at the top of my script.
Any thoughts on how to make this work, i.e. get rid of the trailing spaces to make the comparison work?
Thanks in advance for any pointers in the right direction!
A line like
ECHO !VECTOR_CURRENT_MAP2! >> %VECTOR_LOGFILE%
results in appending the value of the environment variable VECTOR_CURRENT_MAP2 to file with file name stored in environment variable VECTOR_LOGFILE with a trailing space because there is a space before redirection operator >> which is interpreted by Windows command processor as part of the string to output by command ECHO. This space must be removed to get the file name redirected into the log file without a trailing space.
In general it is critical on redirecting a variable string into a file without a space between the variable string and the redirection operator in case of the variable string ends with a space and a number being a valid handle number like 1 or 2 or 3. There are several solutions to workaround this problem like specifying the redirection left to command ECHO, i.e.
>>%VECTOR_LOGFILE% ECHO !VECTOR_CURRENT_MAP2!
But on using delayed expansion as simply necessary here, it is safe to append the redirection at end without a space between exclamation mark and >>, i.e.
ECHO !VECTOR_CURRENT_MAP2!>> %VECTOR_LOGFILE%
The space after redirection operator is ignored by Windows command processor and therefore can be kept although many batch file programmers (like me) with good syntax highlighting don't insert a space after a redirection operator.
On comparing strings with command IF and enclosing one string in double quotes which is always a good idea, it must be made sure that the other string is also enclosed in double quotes. The command IF does not remove the double quotes before comparing the strings. The double quotes are parts of the compared strings.
The condition
IF !LAST_BIT!=="-latest"
is only true if the string assigned to environment variable LAST_BIT would be with surrounding quotes which is never the case with your batch code and therefore the condition is never true.
Correct would be:
IF "!LAST_BIT!"=="-latest"
There is no need to use command DIR to search for files with a pattern in a directory as command FOR is designed for doing exactly this task. Processing of output of command DIR is an extension of FOR available only if command extensions are enabled as by default.
The file extension is defined by Microsoft as everything after last dot in name of a file. Therefore the file extension for your files is pbf respectively .pbf and .osm belongs to the file name.
Command FOR offers several modifiers to get specific parts of a file or directory name. Those modifiers are explained in help output into console window on running in a command prompt window for /?. Help of command CALL output with call /? explains the same for processing parameters of a batch file or subroutine (batch file embedded within a batch file).
Your code with all mistakes removed:
FOR %%M IN (*.osm.pbf) DO (
SET "VECTOR_CURRENT_MAP2=%%~nM"
SET "VECTOR_CURRENT_MAP2=!VECTOR_CURRENT_MAP2:~0,-4!"
ECHO !VECTOR_CURRENT_MAP2!>>%VECTOR_LOGFILE%
SET "LAST7CHARS=!VECTOR_CURRENT_MAP2:~-7!"
ECHO !LAST7CHARS!>>%VECTOR_LOGFILE%
IF "!LAST7CHARS!" == "-latest" (
SET "VECTOR_CURRENT_MAP3=!VECTOR_CURRENT_MAP2:~0,-7!"
) ELSE (
SET "VECTOR_CURRENT_MAP3=!VECTOR_CURRENT_MAP2!"
)
ECHO !VECTOR_CURRENT_MAP3!>>%VECTOR_LOGFILE%
)
Easier would be using this code with using string substitution feature of command SET, i.e. search within a string case-insensitive for all occurrences of a string and replace them with another string which can be also an empty string.
FOR %%M IN (*.osm.pbf) DO (
SET "VECTOR_CURRENT_MAP2=%%~nM"
SET "VECTOR_CURRENT_MAP2=!VECTOR_CURRENT_MAP2:~0,-4!"
ECHO !VECTOR_CURRENT_MAP2!>>%VECTOR_LOGFILE%
SET "VECTOR_CURRENT_MAP3=!VECTOR_CURRENT_MAP2:-latest=!"
ECHO !VECTOR_CURRENT_MAP3!>>%VECTOR_LOGFILE%
)
%%~nM is replaced on execution by Windows command processor by the name of the file without drive, path and file extension resulting for your example in basse-normandie-latest.osm.
The unwanted file name part .osm is removed with the next line in both batch code blocks which chops the last 4 characters from the file name string.
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 /?
set /?
Read the answer on question Why is no string output with 'echo %var%' after using 'set var = text' on command line? for an explanation why I used set "variable=value" on every line which assigns a value string to an environment variable because trailing whitespaces are critical for your task.
So we are running a backup script for my job and until now they just had the script pull the computer name and use that as the folder it creates. The problem that we are encountering is that when we go to then use the restore script it becomes useless.
Our computer names are for example SMITHT#-Year-A.
But I would like the batch script to not use the whole name because often this is used when we change the year of the computer. And because sometimes there are numbers after a persons name there are variying lengths so most of the knowledge I have on deciding start and stop points is coming up useless.
Is there a way to have the batch create a folder using the %COMPUTERNAME% function telling it to stop at the "-" so all we get is the name and number of the person?
To split a string at a certain character use for /F:
for /F "tokens=1 delims=- eol=-" %L in ("%COMPUTERNAME%") do (set SHORTNAME=%L)
This command line stores the string portion before the (first) - into variable SHORTNAME.
For details type for /? in the console window.
To use the above line in a batch script, replace %L by %%L.