What function does the open parenthesis serve in this command?
Why is there no closed parenthesis?
>> datatest.csv.TEMP echo(!modified!
This is the result of a discussion on DosTips about nine years ago.
Your code will redirect the value of !modified! to datatest.csv.TEMP or it will print a blank line in that file if the variable is empty. According to echo /?, the official way to display a blank line is to use echo.. However, if cmd.exe is somehow able to find an executable with no extension called echo (for example, a file in the same directory as the script), that file gets used instead of the regular echo command.
A few alternatives to echo. were considered, including echo\, echo:, echo/ and echo(. echo\ was ruled out in case of a situation where there was a folder called echo that contained a file with the same name as whatever was being echoed. echo/ was ruled out in situations where the string to be displayed started with a ?, because in the case the help was displayed. echo: was ruled out for extremely rare situations where string substitution was being utilized.
Ultimately, echo( was ended up with simply because nobody could find a situation where it didn't work. (Later on, there was some speculation that echo=, echo,, and echo; are all safe to use without weird side effects or edge cases. However, if you are trying to display the literal string /?, the help for echo will be displayed instead.)
The ) is not included because it will get displayed.
Related
I'm creating a batch script to a get a file based on what option the user chooses. The only problem is, the file in the ftp server has a colon and from what i've researched, windows does not accept ":" colon.
Is it possible to replace that character before downloading?
Below is a sample of my code.
Echo open sample.net>first.dat
Echo user>>first.dat
Echo password>>first.dat
Echo ascii>>first.dat
Echo cd directory>>first.dat
Echo lcd folder>>first.dat
Echo get sample-text-10-16-2017_16:36:00:340033.txt>>first.dat
Echo bye>>first.dat
ftp -v -i -s:first.dat
del first.dat
As you can see also, I get a list first of the file names inside the folder for the user to input the file name. I just wrote a specific file name for the example
I'm still not familiar with the for loops in batch but I think that it is one way of replacing the characters in a file name before downloading
[Untried]
get remotefilename localfilename
is apparently valid, so placing a valid windows filename as a second argument should d/l to the file specified.
[Addendum - also untried]
(after Echo lcd folder>>first.dat)
echo mls remotefilesrequired awindowlistfilename>>first.dat
rem this should log in and create awindowslistfilename
rem containing the remote filelist
ftp -v -i -s:first.dat
del second.dat 2>nul
setlocal enabledelayedexpansion
for /f "delims=" %%a in (awindowslistfilename) do (
set "remote=%%a"
echo get !remote! !remote::=.!>>second.dat
)
endlocal
Echo bye>>second.dat
ftp -v -i -s:second.dat
del first.dat
del second.dat
Since I'm not aware of the return format for mls, I'm assuming that it's a simple file-list, one to a line.
This code first executes the ftp log-on palaver and an mls command, creating awindowslistfile locally.
It then deletes second.dat (the 2>nul suppresses error messages like file not found appearing on stderr)
setlocal enabledelayedexpansion and endlocal bracket a mode where the syntax changes such that !var! may be used to access the run-time value of a variable, whereas %var% always refers to the parse-time value.
The for/f command reads the filename (parenthesised) and assigns each line in turn to the metavariable %%a. The delims= option ensures that the entire line is assigned, ignoring the normal tokenising procedure.
A series of individual get commands is then written to second.dat, with the substitution of : by . in the name.
Finally, add the bye and FTP again.
(I'm not sure whether first.dat will also require a bye and second.bat will need to prelimnary commands, but could be...)
Note that it's batch convention to enclose filenames that may contain separators like Space,; in "quotes". How FTP will feel about that, if necessary, I can only guess.
Naturally, extra lines within the loop
set "remote=!remote:x=y!"
could be used to serially replace character sequences x by y if there are any other problematic characters encountered.
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.
I am trying to write a log that a user will create in a batch file, as a small little game, but I can't seem to get the correct directory of the file down. I want to write to this directory:
BatchfileandFolder\subfolder1\subfolder2\ThedataisHere.txt
This is the code I have (I really don't know what I am doing)
Echo Write a piece of text here
set /p UserData=
>>\subfolder1\subfolder2\"ThedataisHere.txt" echo %UserData%
It is essential trying to dig deeper into the directory, but I don't know the exact command, and the help menu for CD, and PATH on the cmd.exe promt don't really help me that much.
Thank you for real human contact, speaking real English
#ECHO OFF
SETLOCAL
SET "logfile=u:\sub folder1\sub folder2\ThedataisHere.txt"
FOR /f "delims=" %%a IN ("%logfile%") DO MD "%%~dpa"
Echo Write a piece of text here
set /p UserData=
>>"%logfile%" echo %UserData%
GOTO :EOF
This method uses a variable logfile so that you aren't forever typing out the name (and avoid the pain if you want to change the names or directories, and the method allows you yo use multiple logfiles easily if you want)
I've deliberately used spaces in directory names to prove the method. The directory gets created immediately after the logfile name is set
append 2>nul to the md instruction line to suppress the directory already exists message
From there, simply use >>"%logfile%" to create the log. The quotes are not required if the filename doesn't contain separators like spaces.
Note that if the first character of the directory specified is \ then the directory is relative to the root, but if it is not then the directory is relative to the current directory on the destination drive. u: is a drive specifier, not a directoryname; I use u: as my test drive. Your choice is up to you.
If the directory structure already exists, it's pretty simple:
#echo off
set /p UserData=Write some text here:
#echo %UserData% >> "subfolder1\subfolder2\TheDataIsHere.txt"
If it doesn't exist already, you have to create it first (tested on Win7 64 bit):
#echo off
if not exist "subfolder1" md "subfolder1"
if not exist "subfolder1\subfolder2" md "subfolder1\subfolder2"
set /p UserData=Write some text here:
#echo %UserData% >> "subfolder1\subfolder2\TheDataIsHere.txt"
Although your description is ample, some important points are missing. It is obvious that you know "How to change the directory that a batch file will output text to", because you use the >> \subfolder\... notation, so this is not your problem. I can only guess that you want to know "How to get the directory where a batch file is located", so you can write to a log file placed two levels below that directory. If this is your problem, then you may use the %~P0 notation, that represent the path of the batch file; that is:
>> "%~P0subfolder1\subfolder2\ThedataisHere.txt" echo %UserData%
Note that the value returned by %~P0 ends in a backslash, so %~P0 must not be separated by an additional backslash from subfolder1; also note that the quotes must enclose the whole path of the file.
If this is not what you want, please carefully describe your real problem. Anyway, try to be clearer in future questions.
I've recently started working with .bat files, and I'm trying to redirect the output to a file.
I've found 2 options, so far:
echo aaa > out.txt - which sends the output of the single echo command to the specified file (can also be appended using >>)
calling the entire file from the cmd using somefile.bat > out.txt (which is actually similar to number 1, as it sends the output of the single command somefile.bat to out.txt)
What I'm looking for is something else - I'm trying to have a line in my file that sends all the output from that point forth to the file.
Thanks!
echo this goes to screen
(
echo this line goes to the file
echo also this line and the ping-output
ping www.stackoverflow.com
echo and this
)>file.txt
echo this goes to screen again
Note:
all inside the block (between ( and )) is parsed at once. If you use variables inside the block, you may need delayed expansion.
There is no universal solution. It depends of the batch file requirements.
For a lot of batch files, the answer from Stephan will work without problems, taking in consideration what he pointed: all the code is inside a block and any variable management inside it may require delayed expansion.
Other alternative is to move the code under a subroutine, calling it with the redirection
#echo off
call :mainProcess %* > outputFile
exit /b
:mainProcess
:: here the batch file begins
echo %1 %2 %3
I'm just starting with batch files, and I'm trying to loop over my Path environment variable with this script:
for %%A in %PATH% do echo %%A
ant I'm getting the error in the title.
While running set I see that path has a value, and the "c:\ant-1.8.4\bin" is what I'm looking for.
I tried playing around with it, and even this:
for %%A in %PATH% do echo TEST
fails with the same error.
Thanks!
edit - clarification
In the end, I want to do a small manipulation on each entry, so Magoo's answer doesn't really solve the problem for me.
#ECHO OFF
SETLOCAL
ECHO %path:;=&ECHO(%
This should show the elements of your path one to a line. Your question isn't clear - what do you actually want to do?
Adapting answer from comments in original question
There are two different sets of parenthesis in a for command:
for %%x in (set) do (commands)
The first set of parenthesis delimit the set of elements being processed and are needed always.
The second set of parenthesis are needed only if the list of commands to execute for each of the iterations of the for command extends over several lines.
And yes, spaces, &<>!;:," and some more special characters need to be taken into consideration when dealing with for command and file/folder paths.