I am looping through a series of sub-directories using a for loop
For /R %1 %%f IN (*.shp) do (
I need to convert the file path %%f from a backslash to a forward slash.
set old=%%f
set new=!old:\=/!
echo !new!
echo|(set /p="CALL spatial.importShapefileToLayer('%%~nf', '!new!');" & echo.) >> test.cypher
As the code is now, the !new! text is written as a literal to the test.cypher
CALL spatial.importShapefileToLayer('N00E006_D100_S004_T007_L00_U0_R0', '!new!');
What I need to write to the output is the value of !new!
CALL spatial.importShapefileToLayer('N00E006_D100_S004_T007_L00_U0_R0', 'c:/test/N00E006_D100_S004_T007_L00_U0_R0.shp');
The echo of the !new! to the screen does show the correction of backslash to forward slash, so the !new! variable is receiving the correction
Ideas on how to correctly use the !new! contents in the output string would be appreciated.
edit : setlocal EnableDelayedExpansion
was included in the batch file
Somebody smarter than I am will likely direct you to How does the Windows Command Interpreter (CMD.EXE) parse scripts? for an explanation about why this is happening, but as far as I can tell, the parentheses (or maybe the pipe) are causing things to get expanded and processed in the wrong order so !new! never has a chance to get expanded properly.
To fix this, move the ( to the start of the line.
#echo off
setlocal enabledelayedexpansion
if exist test.cypher del test.cypher
for /r "%~1" %%A in (*.shp) do (
set old=%%A
set new=!old:\=/!
echo !new!
(echo|set /p="CALL spatial.importShapefileToLayer('%%~nA', '!new!');" & echo.) >> test.cypher
)
Related
I've set up an app for a couple of friends and me in batch with a auto-updating system, but I need to add a line of code in the auto-updating system. I decided to completely rewrite the file, it takes a long time to add 'echo' in from to every line and, '>>text.txt' at the end of every line and added '^' when needed, so I was wondering if there was an easier way of writing lot's of code to a file in batch.
Example:
#echo off
rem I need a way to do the following without adding 'echo' and '>>text.txt'
echo echo Checking for updates... >text.txt
echo echo 1.4 ^>^>new.txt >>text.txt
echo ping localhost -n 2 ^>nul >>text.txt
rem and so on and so on.
Or if there is a way to simply add a new line of code in a specific place in the file, that would also help!
Thanks in advance!
The following is how you can more easily and efficiently do what your current code does, by removing all of those individual write processes.
#( Echo #Echo Checking for updates...
Echo #(Echo 1.4^)^>^>"new.txt"
Echo #(%__AppDir__%ping.exe LocalHost -n 2^)^>NUL
)>"text.txt"
There are other possibilities, but at this time, based on the lack of information in your question, I'm reluctant to expand further at this time.
If I understand correctly, then you could do the following:
in the batch file, prepend each line of text that you want to output with :::: (this constitutes an invalid label that is going to be ignored);
then use the following code:
rem // Redirect to file:
> "text.txt" (
rem // Find all lines that begin with `::::` and loop over them:
for /F "delims=" %%T in ('findstr "^::::" "%~f0"') do (
rem // Store currently iterated line:
set "TEXT=%%T"
rem // Toggle delayed expansion to avoid loss of `!`:
setlocal EnableDelayedExpansion
rem // Remove `::::` prefix and output remaining line:
echo(!TEXT:*::::=!
endlocal
)
)
replace set "TEXT=%%T" by call set "TEXT=%%T" if you want to enable percent expansion within the returned text (so it could, for example, contain %~nx0, which would then be expanded to the file name of the script).
I am using this technique a lot (without the output redirection) for help systems in my batch files (/?).
Your asked
I need a way to do the following without adding echo and >>text.txt
The script takes advantage of the line continuation character, the caret ^.
The first character after the caret ^ is always escaped, so do linefeed characters:
#echo off
SETLOCAL EnableDelayedExpansion
call :init
>text.txt (
echo #echo off%NL%
Checking for updates...%NL%
>^>new.txt echo 1.4%NL%
>NUL ping localhost -n 2
)
ENDLOCAL
exit /b
:init
( set LF=^
%= 0X0D FORM FEED =%
)
::0X0A Carriage Return
FOR /F %%a in ('copy /Z "%~f0" nul') do set "CR=%%a"
::Create newline/line continuation character
set ^"NL=^^^%LF%%LF%^%LF%%LF%^^" %= Unix-Style Endings \n =%
::set ^"NL=%CR%^^^%LF%%LF%^%LF%%LF%^^" %= Windows-Style Endings \r\n =%
exit /b
The variable %LF% is a escaped linefeed, and %NL% is a escaped %LF% plus a escaped caret ^ for line continuation.
The code
>^>new.txt echo 1.4%NL%
>NUL ping localhost -n 2
might seem strange. Why isn't the first caret ^ escaped?
Because %NL% already escaped it.
Sources:
Explain how Windows batch newline variable hack works
https://stackoverflow.com/a/5642300/12861751
https://www.dostips.com/forum/viewtopic.php?t=6369
I would like to create a logfile with this information :
echo %time%;%date%;%computername%;"findstr /I "%%a" %MYFILES%\Dir_ALL.txt" >> %computername%_File.csv
How can I write something that will not write "findstr /I ..." but the output of this command ?
I would like to have everything in the same line on my output file.
Thank you
write a line without linefeed with set /p, followed by the second line:
<nul set /p .=%time%;%date%;%computername%;>>%computername%_File.csv
findstr /I "%%a" %MYFILES%\Dir_ALL.txt>>%computername%_File.csv
Note: Because of the %%a I guess, you are using this codefragment inside a forstatement. I suggest using !time! instead of %time% to get the actual time (using delayed expansion of course)
You have to set a variable with the command result. This is answered in Windows Batch help in setting a variable from command output, using a dummy for-loop whose loop variable is set from the content of a file.
That would be something like this:
findstr /I "%%a" %MYFILES%\Dir_ALL.txt >%temp%\temp.txt
for /f %%i in (%temp%\temp.txt) do echo %time%;%date%;%computername%;%%i >> %computername%_File.csv
del %temp%\temp.txt
There is a limitation on this: the variable cannot contain multiple lines. However, rephrasing your script fragment as a loop would probably solve that issue as well.
The MSDN article on set shows some additional features which you can use to control how the data from the file is parsed. Normally it parses the result into tokens separated by spaces. But you can override that using the delims keyword.
I'm currently looping threw the subfolders of a known directly. I would like to grab the folder that contains the file I'm looking for, but only that folder's name, not the whole path, and preferably in a different variable to be use later on in the batch file ...
pause
CD c:\%username%\testFolder\Program\OLD\
For /R %%G in (test.t?t) do Echo %%G
pause
Now, this shows me the file I'm looking for : C:\User\testFolder\Program\OLD\myfile\exemple1\test.txt
what I would like is to replace the Echo %%G to set in a variable the "unknown" folders and subfolder, something along the line of
For /R %%G in (test.t?t) do set var1 = myfile\exemple1
anyone can point to what I'm missing ?
If you for /? in a cmd console, you'll see runtime variables on the last couple of pages. Using %%~dpG notation you can get the full drive\path specification of matched files. Then, using substring substitution and delayed expansion, replace %CD% with nothing. Finally, you can strip the leading and trailing backslash with a numeric substring -- !varname:~1,-1!.
#echo off
setlocal enabledelayedexpansion
cd /d "c:\%username%\testFolder\Program\OLD\"
for /R %%G in (test.t?t) do (
set "var1=%%~dpG"
set "var1=!var1:%CD%=!"
if "!var1!"=="\" (echo .\) else echo(!var1:~1,-1!
)
If you wish, you can prevent echoing duplicates by echoing only if the previous match does not equal the current one.
#echo off
setlocal enabledelayedexpansion
cd /d "c:\%username%\testFolder\Program\OLD\"
for /R %%G in (test.t?t) do (
set "var1=%%~dpG"
set "var1=!var1:%CD%=!"
if not "!var1!"=="!prev!" (
if "!var1!"=="\" (echo .\) else echo(!var1:~1,-1!
)
set "prev=!var1!"
)
There are more than 10 html files with image tags. Every time we deploy our build onto test site we need to change the img source. for eg <img src=/live/Content/xyz.png />
to <img src=/test/Content/xyz.png />.
After looking around and reading for sometime, i have come up with the following batch script, however i cant figure out how do i go further from here :
for /r %%i in (*.html) do echo %%i
for %%f in (*.html) do (
FOR /F %%L IN (%%f) DO (
SET "line=%%L"
SETLOCAL ENABLEDELAYEDEXPANSION
SET "x= <--------------------WHAT DO I SET HERE?
echo %x%
ENDLOCAL )) pause
This is my first batch script, could anyone please guide me in the right direction?
#ECHO OFF
SETLOCAL enabledelayedexpansion
for /r U:\ %%i in (*.html) do (
echo found %%i
SET outfile="%%~dpni.lmth"
(
SETLOCAL disabledelayedexpansion
FOR /F "usebackq delims=" %%L IN ("%%i") DO (
SET "line=%%L"
SETLOCAL ENABLEDELAYEDEXPANSION
SET "line=!line:/live/=/test/!
echo !line!
ENDLOCAL
)
ENDLOCAL
)>!outfile!
)
pause
GOTO :EOF
How about this development?
Notes:
I've modified your FOR/R to ECHO the HTML file being processed and use %%i rather than switching to %%f. U: is my RAMDRIVE; you'd need to modify that to suit.
outfile is set to generate a filename which matches the HTML filename, but with a .lmth extension (can't update in-place) - it gets that from the ~dpn prefixing the i, which means the drive, path and name of the file %%i. It's quoted to take care of potential spaces in the filename or pathname.
The next logical statement is (for /f...[lines] )>!outfile! which sends any echoed text to a NEW file !outfile!. The enabledelayedexpansion in the second physical line of the batch makes !outfile! the RUN-TIME value - as it is changed within the FOR r outer loop.
Since the actual HTML filename in %%i may contain spaces, it needs to be quoted, hence the 'usebackq' clause in the FOR/F. The delims= clause ensures that the ENTIRE line from the file "%%i" is applied to %%L - not just the first token (well, actually, makes the entire line the first token).
The SET command substitutes the string "/test/" for any occurrence of "/live/" in the RUN-TIME value of the variable lineand assigns the result to line. The resultant value is then ECHOd - which is redirected to outfile
Note that in your original, you would be assigning x in the set x= but echo %x% would have reproduced x as it stood when the line was PARSED because batch substitutes the value of any variable for %var% as part of the parsing phase. Consequently, the line would have become simply ECHO (since x would likely be unassigned) and bizarrely would have reported the echo state (Echo is OFF)
A couple of gatchas here. First, % and some other characters are notoriously hard to process with batch, so be careful. Next, FOR/F will bypass empty lines. This can be overcome if required. Third, this will replace ANY occurrence of /live/ in any case with /test/
Good luck!
Edit to support exclamation marks: 20130711T0624Z
Added SETLOCAL enabledelayedexpansion line and ENDLOCAL just before )>!outfile! to match
I don’t know if this is possible but I would like to make a batch, which replaces all, the backslashes contained in a txt file (C:\locations) with forward slashes.
THX..
EDIT:
Im trying to loop:
set str1=!Var1!
echo.%str1%
set str1=%str1:\=/%
to work together with:
set file=C:\text1.txt
FOR /F %%i IN (%file%) DO (
set username=%%i
echo (load "%%i") >> C:\text.txt
)
what I have so far is:
ECHO Retreving list of files...
dir /s /b c:\ICT\AUTOCAD_2010\*.LSP > C:\BART1.txt
Echo Looping variables...
set file=C:\text1.txt
FOR /F %%1 IN (%file%) DO (
set fred=%%1
echo %%1 > C:\tempme.txt
)
set fred=C:\tempme.txt
set fred=%fred:\=/%
echo (load "%fred%") >> C:\text2.txt
however this returns:
(load "C:/tempme.txt")
which is incorect.
Windows' PowerSheel is too limited for that. I suggest you using a scripting language like Perl. Here's a quick script that does that:
my #file = <STDIN>;
my $text = join('', #file);
$text =~ s/\\/\//g;
print($text);
You can launch it like
perl foo.pl < example.txt > result.txt
Using sed as suggested by Tichodroma is another very good option.
I'm a little confused as to what you really want. Your sample code has a FOR ... IN that only has one file in the IN (), i.e. the content of %fred%. Then you write that one filename into a temporary file. Afterwards you have SET that replaces the backslash with a forward slash in the name of the temporary file. But this never touches any file.
However, in your opening segment you want to replace backslashes with forward slashes in a file. So I'm focusing on that part. That would be done this way:
#ECHO OFF
SETLOCAL EnableDelayedExpansion
REM Here's a backslash: \
FOR /F "delims=" %%a IN ('TYPE %0') DO (
SET line=%%a
ECHO !line:\=/!
)
Please note that for simplicity this little batch file parses itself (%0) and, therefore, only replaces that one backslash. However, feel free to put whichever file next to TYPE.
EnableDelayedExpansion makes the syntax with the ! work (see SET /? for more info about delayed expansion). TYPE obviously writes a file to the console. The FOR /F "delims=" now grabs the output of that line per line (since delims= defines no delimiter for the tokenizer of FOR). The line-variable is necessary, because I don't think that there is a proper way to make the ECHO-line work with %%a.
The only downside is that this will remove all empty lines from the original file. I don't know if that's a problem for you.