I am trying to edit out the quotation marks that have been inputed into a text file using .bat.
echo %name%>./User_Records/%username%.txt
in the text file it is saving as
"Firstname Lastname"
I am trying to add to the batch file so that it will edit the *.txt file and delete the quotation marks if they are saved in that text file.
Can anyone help me?
I have been trying to do this for weeks. I want the output to look like
Firstname Lastname
Try replacing all instances of " in the %name% variable by using Environment variable substitution (see set /? for more)
#echo off
set "name=%name:"=%"
echo %name%>./User_Records/%username%.txt
If you are trying to replace the quotation marks after the text file has been saved, then refer to this previous question
echo %name:"=%>.\User_Records\%username%.txt
should strip the quotes before they are recorded, if that's what your question is.
Note that path-separators in windows are \ not /.
But - if your question is about files that already exist then probably the easiest way is to use your editor. Depends a little on quite how many files you have to process - which you haven't specified.
The bat file you are using should really be altered, especially as the line you've provided from it has some issues, (mostly already mentioned).
SetLocal EnableDelayedExpansion
(Echo=!name:"=!)>"User_Records\%username%.txt"
EndLocal
If you have no control over that bat file then something like this should do what you want:
#For /F "UseBackQ Delims=" %%A In ("User_Records\%username%.txt") Do #Echo(%%~A
Alternatively:
#Set/P "FullName="<"User_Records\%username%.txt"
#Echo(%FullName:"=%
If the name read from text file is assigned to environment variable name using set name="..." syntax, then this is the cause of the double quotes in output string.
It makes a big difference if string assigned to environment variable is enclosed in double quotes or the entire parameter string of command SET. Read answer on Why is no string output with 'echo %var%' after using 'set var = text' on command line? to get knowledge about the big difference between using set "variable=string" versus set variable="string".
But it is of course possible to remove all double quotes from string assigned currently to environment variable name by using a string substitution:
set "name=%name:"=%"
All occurrences of " in string of name are replaced by an empty string and resulting string is assigned again to environment variable name.
But be aware that this command line
echo %name%>"./User_Records/%username%.txt"
could result in an unwanted behavior, for example if the name assigned to environment variable name is C&A. The ampersand found by Windows command interpreter after expanding environment variable name and before execution of command ECHO is interpreted now as AND operator and not anymore as literal character to output by ECHO.
One solution is using delayed expansion, for example:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Environment variable name is defined with delayed expansion disabled
rem making it possible to assign an exclamation mark as literal character
rem without the need to escape it as it would be necessary when delayed
rem expansion would be enabled already here at this time.
set "name=C&A!"
rem Enable delayed expansion which results in pushing on stack current
rem state of command extensions and of delayed expansion, the current
rem directory path and the pointer to current environment variables list
rem before creating a copy of all environment variables being used further.
setlocal EnableDelayedExpansion
rem Output the value of environment variable name using delayed expansion
rem with redirection into a text file being named like the currently used
rem user account name which of course can contain a space character or
rem other characters requiring enclosed file name with relative path in
rem double quotes.
echo !name!>".\User_Records\%username%.txt"
rem Delete all environment variables, restore pointer to previous set of
rem environment variables, restore current working directory from stack
rem restore states of command extension and delayed expansion from stack.
endlocal
rem Explicitly call ENDLOCAL once again for initial SETLOCAL command.
rem That would not be necessary because Windows command interpreter
rem runs implicitly ENDLOCAL for each local environment still being
rem pushed on stack.
endlocal
An alternate solution is using command FOR for an implicit delayed expansion:
#echo off
set "name=C&A!"
set "name=%name:"=%"
for /F "delims=" %%I in ("%name%") do echo %%I>".\User_Records\%username%.txt"
set "name=
See also the answers on Batch: Auto escape special characters.
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 /?
set /?
setlocal /?
Read also the Microsoft article about Using Command Redirection Operators.
Related
Hello I am trying to rename all files ending with "VA.pdf" to "PA.pdf" using batch code
I tired this code but it is not working
REN *VA.pdf *PA.pdf
Appreciate any help
There can be used for this file renaming task:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
if exist "*!*VA.pdf" goto ExtendedVersion
setlocal EnableDelayedExpansion
for /F "eol=| delims=" %%I in ('dir *VA.pdf /A-D-L /B 2^>nul') do (
set "FileNamePDF=%%~nI"
set "FileNameNew=!FileNamePDF:~0,-2!PA%%~xI"
if not exist "!FileNameNew!" ren "!FileNamePDF!%%~xI" "!FileNameNew!"
)
endlocal
goto EndBatch
:ExtendedVersion
echo INFO: Extended version required because of a PDF file with exclamation marks.
for /F "eol=| delims=" %%I in ('dir *VA.pdf /A-D-L /B 2^>nul') do (
set "FileNamePDF=%%~nI"
setlocal EnableDelayedExpansion
set "FileNameNew=!FileNamePDF:~0,-2!PA%%~xI"
if not exist "!FileNameNew!" ren "!FileNamePDF!%%~xI" "!FileNameNew!"
endlocal
)
:EndBatch
endlocal
There is defined first the required execution environment with the first two command lines.
The IF condition in the third command line quickly checks if there is any PDF file with case-insensitive VA in the file name before the file extension .pdf containing one or more exclamation marks in the file name. The extended version of the processing loop is required if this condition is true.
The standard version enables first required delayed expansion. Then a FOR loop is used which runs in background with Windows installed into C:\Windows:
C:\Windows\System32\cmd.exe /c dir *VA.pdf /A-D-L /B 2>nul
The internal command DIR of cmd.exe searches
in the current directory as defined by the process starting cmd.exe for processing the batch file
for just file names because of option /A-D-L (attribute not directory and not link)
matching case-insensitive the wildcard pattern *VA.pdf in long or short 8.3 name
and outputs in bare format because of option /B just the file names with file extension, but without file path.
An error message output to handle STDERR (standard error) on DIR does not find any file system entry matching the criteria is suppressed by redirecting this error message to the device NUL.
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 with option /F is used here to get a list of file names of *VA.pdf files loaded into memory of cmd.exe before really doing the file renames as otherwise it could happen especially on FAT drives (FAT32, exFAT) that some PDF files are skipped or processed more than once (on rename not possible).
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 PDF 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 PDF 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.
The current file name without file extension .pdf is assigned first to the environment variable FileNamePDF.
Next a string substitution is used to get from the string value of the environment variable FileNamePDF the file name without the last two characters VA concatenated with the string PA and the file extension .pdf assigned to the environment variable FileNameNew.
If there is not already a PDF file ending with PA in the file name before the file extension, there is next executed the command REN to rename the *VA.pdf file to *PA.pdf.
The command ENDLOCAL after the loop restores the previous environment before enabling delayed expansion and the command GOTO instructs the Windows Command Processor to continue processing the batch file with the command line below the label EndBatch which contains one more ENDLOCAL to restore the environment on starting the batch file processing.
The extended version is nearly the same as the standard version. The difference is that delayed variable expansion is not enabled on assigning the file name of the current VA.pdf file without the file extension to the environment variable FileNamePDF. That avoids interpreting the exclamation mark(s) in the file name as beginning/end of a delayed expanded variable reference resulting in a manipulation of the file name string before assigning it to the environment variable as it would happen with delayed expansion already enabled.
The extended version enables next delayed variable expansion inside the loop, does the same as the standard version and restores finally the previous environment before processing the next *VA.pdf file.
The extended version is slower because of the environment variables list copy and the other operations made in background by every execution of SETLOCAL as explained in full details in this answer. The command ENDLOCAL in the loop is required to avoid a stack overflow on processing lots of PDF files.
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.
echo /?
endlocal /?
for /?
goto /?
if /?
ren /?
set /?
setlocal /?
In my second if statement, I want to filter out "tool" or "tool.bat" from the final list of filenames. However, the final list of filenames includes "tool" and total_bags is being incremented. I was wondering what I did incorrectly that's causing the program to not catch this case.
set /A total_bags=0
set target=%~1
if "%target%"=="" set target=%cd%
set LF=^
rem Previous two lines deliberately left blank for LF to work.
for /f "tokens=1 delims=. " %%i in ('dir /b /s /a:-d "%target%"') do (
set current_file=%%~ni
echo !unique_files! | find "!current_file!:" > nul
if NOT !ERRORLEVEL! == 0 (
if NOT !current_file! == "tool.bat" (
set /A total_bags=total_bags+1
set unique_files=!unique_files!!current_file!:
)
)
)
echo %unique_files::=!LF!%
echo %total_bags%
endlocal
The condition if NOT "%current_file%" == "tool.bat" as initially used does not work because of %current_file% is replaced already by current string of the environment variable current_file respectively an empty string on Windows command processor is processing the entire command block starting with ( and ending with matching ) before executing command FOR. That can be seen on debugging the batch file. See also Variables are not behaving as expected for a very good and short example explaining how the Windows command interpreter (CMD.EXE) parses scripts.
It is in general not advisable to assign the string already assigned to a loop variable to an environment variable which is not further modified inside a FOR loop. It would be better to use %%~ni everywhere in your code on which the current file name needs to be referenced.
The usage of delayed expansion requires enabling it with setlocal EnableDelayedExpansion (or with setlocal EnableExtensions EnableDelayedExpansion to enable explicitly also the command extensions enabled by default) as it is not enabled by default in comparison to the command extensions. Then the Windows command processor parses each command line a second time and expands !current_file! on execution of command IF.
But even if NOT !current_file! == "tool.bat" evaluates always to true for the batch file with name tool.bat because of set current_file=%%~ni results in assigned to the environment variable current_file only the string tool (file name without file extension) and the left string is not enclosed in double quotes while the right string is always enclosed in double quotes. The command IF does not remove the double quotes from right string before comparing the two strings.
The batch file in question misses also set unique_files= above the FOR loop to undefine explicitly the environment variable unique_files in case of being already defined by chance on starting the batch file, for example from a previous execution within a command prompt window.
Another problem with the batch file in question is that maximum string length of variable name + equal sign + string assigned to the environment variable is 8191 characters which is a problem on several thousands of file names are concatenated to a long string assigned to one environment variable like unique_files.
I suggest to use this batch file with comments explaining it.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Delete all environment variables of which name starts very unusual
rem with a question mark existing already by chance (with exception of
rem those environment variables with multiple question marks in name).
for /F "delims=?" %%I in ('set ? 2^>nul') do set "?%%I?="
rem Search with the string passed as first argument or simply within current
rem directory recursively for all files and define for each file name an
rem environment variable with a question mark at beginning and one more at
rem end of the variable name. A file name cannot contain a question mark.
rem The value assigned to the environment variable does not matter. As it
rem is not possible to define multiple environment variables with same name
rem and environment variable names are case-insensitive, there is just one
rem environment variable defined on multiple files have same file name.
rem The batch file itself is ignored because of the IF condition.
for /F "delims=" %%I in ('dir "%~1" /A-D /B /S 2^>nul') do if not "%%I" == "%~f0" set "?%%~nI?=1"
rem Initialize the file counting environment variable.
set "FileCount=0"
rem Output all file names which are the environment variable names sorted
rem alphabetically with the question marks removed and additionally count
rem the number of file names output by this loop.
for /F "eol=| delims=?" %%I in ('set ? 2^>nul') do set /A "FileCount+=1" & echo %%I
rem Output finally the number of unique file names excluding file extensions.
echo %FileCount%
rem Restore initial execution environment which results also in the
rem deletion of all environment variables defined during batch execution.
endlocal
It does not use delayed expansion and for that reason works also for file names containing one or more ! in file name which would be processed wrong on enabling delayed expansion on line set current_file=%%~ni because of the exclamation mark(s) in file name would be interpreted as begin/end of a delayed expanded environment variable reference.
There is defined an environment variable for each unique file name. The number of environment variables is limited only by the total available memory for environment variables which is 64 MiB. That should be enough even for several thousands of unique file names in the directory tree.
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 %~f0 which references full name of argument 0 which is the full qualified file name of the currently processed batch file and %~1 referencing first argument with perhaps existing surrounding " removed from argument string.
dir /?
echo /?
endlocal /?
for /?
if /?
rem /?
set /?
setlocal /?
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 the FOR command lines to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir or set command line with using a separate command process started in background with %ComSpec% /c and the command line within ' appended as additional arguments.
I want to insert data (only rows having extended keyword) present in .txt file into Oracle database in the format ID,Data,Date,Project Name where ID, date and project name are present in environment variables.
File.txt has below data:
Writing main object(name=abc)
writing Extended object (name=%abc(123&rest,type=pqr)
logdata.txt should have below data:
A1234C,(name=%abc(123&rest,type=pqr),12022018_11:12:20,DEV:Sales Project
While copying the data, special characters like %,( etc present in the file.txt are missing in the output file logdata.txt.
Please find below code :
set file=D:\MSTR_CICD\file.txt
for /F "usebackq tokens=2*delims=(" %%a in (`findstr "extended" "%file%"`) do (
set /A i+=1
call set array[%%i%%]=%%a
call set n=%%i%%
)
for /L %%i in (1,1,%n%) do call echo %User_ID%,%%array[%%i]%%,%Timestamp%,%proj% >> D:\MSTR_CICD\Batch_Script\logdata.txt
Please correct the code or let me know how can i achieve this. Also, my input file can have any special character as it contain logs of an application.
This batch file can be used for this task:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "proj=DEV:Sales Project"
set "User_ID=A1234C"
set "Timestamp=12022018_11:12:20"
set "InputFile=D:\MSTR_CICD\file.txt"
set "DataFile=D:\MSTR_CICD\Batch_Script\logdata.txt"
if exist "%InputFile%" (
for /F delims^=^ eol^= %%I in ('%SystemRoot%\System32\findstr.exe /I /C:Extended "%InputFile%"') do (
set "DataLine=%%I"
setlocal EnableDelayedExpansion
set "DataLine=!DataLine:*(=(!"
set "DataLine=!DataLine:"=""!"
echo %User_ID%,"!DataLine!",%Timestamp%,%proj%
endlocal
)
) >"%DataFile%"
if exist "%DataFile%" for %%I in ("%DataFile%") do if %%~zI == 0 del "%DataFile%"
:EndBatch
endlocal
FINDSTR runs in the separate command process started by FOR in background with cmd.exe /C a case-insensitive, literal search for the string Extended on the input file and outputs all lines containing this string to handle STDOUT.
FOR captures this output and processes them line by line. FOR ignores empty lines and by default also lines starting with a semicolon because of ; is the default end of line character. And FOR splits up the line into substrings (tokens) using space/tab as delimiter and assigns just the first substring to specified loop variable by default.
By using the FOR option string delims^=^ eol^= an empty list of delimiters and and no end of line character is set to disable line splitting and ignoring lines starting with a semicolon. As this special option string cannot be enclosed in double quotes, it is necessary to escape the space and the two equal signs with caret character to get those three characters outside a double quoted argument string interpreted as literal characters and not as argument string separators.
The entire line as output by FINDSTR found in file is assigned to environment variable DataLine. This is done with delayed environment variable expansion disabled to process also lines correct containing one or more exclamation marks. Otherwise cmd.exe would double parse the line set "DataLine=%%I" after having replaced %%I by the current line and would interpret every ! in the line as begin/end of an environment variable reference resulting in unwanted modification of the line before assigning it to the environment variable.
The usage of command CALL on a line with command SET results also in double parsing the command line before executing the command SET which is the reason why some characters are missing in the environment variables array produced by your code.
For details see also How does the Windows Command Interpreter (CMD.EXE) parse scripts?
After having assigned the line to the environment variable, it is necessary to enable delayed expansion to further process the data line in the FOR loop. That makes the batch file slow, but can't be avoided in this case. Read this answer for details about the commands SETLOCAL and ENDLOCAL.
The first modification on the data line is removing everything left to first (.
The second modification on the data line is replacing all " by "" in the line to escape every double quote according to CSV specification.
Then the remaining data line is output together with the other data enclosed in double quotes as the data line can contain also one or more commas which requires according to CSV specification that the data is enclosed in double quotes.
For CSV specification read for example the Wikipedia article about comma-separated values.
Everything output by ECHO inside FOR loop is redirected to the specified data file which overwrites a by chance already existing data file with same name.
It is possible that FINDSTR does not find any line containing Extended in any case resulting in producing a data file with 0 bytes. The empty data file is deleted by the second FOR.
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.
del /?
echo /?
endlocal /?
findstr /?
for /?
goto /?
if /?
set /?
setlocal /?
I am making a query on a txt file via Windows command prompt, but the output displayed is actual content of txt file, instead of system variable.
Any idea how can I amend that?
FOR /F "tokens=1,2 delims=," %%G IN (Backup_Folder.txt) DO (
echo %%H
)
Output is
%USERPROFILE%\Documents\Electronic Arts
instead of
C:\Users\UserName\Documents\Electronic Arts
Content of Backup_Folder.txt is:
EA,%USERPROFILE%\Documents\Electronic Arts
I suggest to use in the batch file:
for /F "tokens=1* delims=," %%G IN (Backup_Folder.txt) do call echo %%H
It is better to use tokens=1* instead of tokens=1,2 in case of the folder path stored in the text file contains per chance also a comma, for example:
EA,%USERPROFILE%\Documents,Settings\Electronic Arts
The asterisk after 1 means the rest of the line after the comma(s) after first comma delimited string without further splitting up the line on commas. So with tokens=1* the loop variable G gets assigned EA and loop variable H gets assigned %USERPROFILE%\Documents,Settings\Electronic Arts. The usage of tokens=1,2 results in H gets assigned just %USERPROFILE%\Documents, for that example.
The command CALL is necessary in this specific case to get on execution of the body of the loop after replacing %%H by %USERPROFILE%\Documents\Electronic Arts in first parsing step the command line parsed a second time by Windows command interpreter to expand additionally %USERPROFILE%.
When the folder path read from text file is assigned to an environment variable, I recommend to use as command set "FolderPath=%%~H" or call set "FolderPath=%%~H" for getting all environment variable references in folder path already expanded before assigning the folder path to the environment variable.
The tilde character between %% and H results on a folder path like "%USERPROFILE%\Documents & Settings\Electronic Arts" stored in the text file that the surrounding double quotes are removed making it possible to use the environment variable for example in a command line like:
if exist "%FolderPath%\Game\game.exe" echo Game exists.
A space as well as &()[]{}^=;!'+,`~ in a file/folder name without or with path require the usage of surrounding double quotes as output by Windows command interpreter on last help page on running in a command prompt window cmd /?. In argument strings not being a file/folder name/path the additionally possible characters |<> require also that the entire argument string is enclosed in straight double quotes to get those redirection operators interpreted as literal characters.
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 /?
for /?
set /?
I'm over my head with this - spent too much time searching already - evidently I don't understand the basics of CMD variables etc. - and it always gives me such a headache
why wouldn't this work?
for %a in (*) do ( set tmpx=%a & echo %tmpx% )
the above code outputs the value of %tmpx% in some other scope - and it is always constant
yes, i run setlocal ENABLEDELAYEDEXPANSION
basically i need to do a simple rename of all files in folder from constantstring_somenameXX.tif to somenameXX.tif, where i.e. constantstring=0000000005
i had to use set because other posts rightly suggested that %a in a for loop has a special behaviour, and the substitutions wouldn't work for it as it is.
i would prefer not to use scripts and/or powershell - unless not using them is impossible
thank you
for %a in (*) do ( set tmpx=%a & echo %tmpx% )
The problem with the previous code is delayed expansion. Yes, you enabled it, but you have not used it, and depending on how you enabled it, it will not work
In cmd, when a line or block of lines (code inside parenthesis) is reached, it is first parsed and then executed. During the parse phase, variable read operations are removed from the command, replaced with the value in the variable before the command starts to execute. So, if you change the value of a variable inside a line/block you can not retrieve the changed value inside the same line/block as there are no variable reads (they were replaced)
setlocal enabledelayedexpansion allows to replace (where needed) the variable read syntax from %var% to !var!, indicating to the parser that the read operation will be delayed until the execution phase.
So, in your case, your code should have been something like
setlocal enabledelayedexpansion & for %a in (*) do ( set "tmpx=%a" & echo !tmpx! )
BUT this will not work (in default configured environments).
cmd has two execution modes: batch file and command line. In your case, you are using command line (no escaped percent sign in for loop) and in command line mode the setlocal enabledelayedexpansion will not work. It is intended for batch files (see setlocal /?)
How to make it work from the command line? By default cmd is started with delayed expansion disabled and you can not enable it if not inside a batch file. But you can start cmd with delayed expansion enabled and run your command in this started instance (see cmd /?)
cmd /v:on /c "for %a in (*) do ( set "tmpx=%a" & echo !tmpx! )"
Anyway, to solve your rename problem, delayed expansion is not needed
for %a in (*_*.tif) do for /f "tokens=1,* delims=_" %b in ("%~nxa") do echo ren "%a" "%c"
That is, for each tif file with an underscore, take the name and extension of the file (%~nxa) as a string, and using the underscore as a delimiter between tokens, retrieve the first token (the text on the left of the first underscore) in %b and the rest of the text (to the right of the underscore) into %c. Now, just rename the original file name (stored in %a) to the contents of %c (the text on the right of the underscore)
In this code rename operations are only echoed to console. If the output is correct, remove the echo command.
! is the character to use rather than % when wanting execution time value. % does when it's read value.
CMD was written by IBM engineers and they were trying to make MSDos a programming language while making sure Dos commands ran the same. So we get a hodge podge.
& seperates commands on a line.
&& executes this command only if previous command's errorlevel is 0.
|| (not used above) executes this command only if previous command's errorlevel is NOT 0
> output to a file
>> append output to a file
< input from a file
| output of one command into the input of another command
^ escapes any of the above, including itself, if needed to be passed to a program
" parameters with spaces must be enclosed in quotes
+ used with copy to concatinate files. E.G. copy file1+file2 newfile
, used with copy to indicate missing parameters. This updates the files modified date. E.G. copy /b file1,,
%variablename% a inbuilt or user set environmental variable
!variablename! a user set environmental variable expanded at execution time, turned with SelLocal EnableDelayedExpansion command
%<number> (%1) the nth command line parameter passed to a batch file. %0 is the batchfile's name.
%* (%*) the entire command line.
%<a letter> or %%<a letter> (%A or %%A) the variable in a for loop. Single % sign at command prompt and double % sign in a batch file.