I had the below code in one of the make files.
#for /F "skip=2 Delims=" %%i in ('<somefile>') do echo Code-%%i
Could anybody tell what is this batch command would do?
As it is written
#for /F "skip=2 Delims=" %%i in ('<somefile>') do echo Code-%%i
this means: Execute (not read file, execute, there are simple quotes) <somefile>, take its output to standard stream, skip the two first lines, and for each line with content, assign this line contents to %%i, then, also for each line, output to console the text Code- followed by the content of the readed line (that is inside %%i).
The # at the start of the line means not to echo to console the for command.
The delims with no value assigned indicates that lines should not be considered as a concatenation of fields with a delimiter between them, that have to be splitted.
Related
I have a task to query some hostnames for their serial number stored in the BIOS. I have the hostnames in a text file gets processed with a for loop, the clients are queried for the serial number with another for loop, and the result is directed into another text file.
This works no problem if the host is offline or doesn't respond. The hostname is written to the text file and the serial number is blank, and the script then moves on to the next entry in the input file. But if the host responds and a serial number is stored in the variable, the script initially writes to the output file as it should, but then it writes another line with the same hostname and a blank serial number before moving onto the next line in the input file.
#ECHO OFF
set list=c:\temp\input.txt
for /F %%C in (%list%) do (
for /F "skip=1" %%S in ('wmic /node:%%C bios get serialnumber') do (
echo %%C - %%S >>c:\temp\output.txt)
)
pause
This results in output that looks like this:
DC6068WA00829 -
DC6054WA00178 -
DC6061WA00065 - R93NSI3
DC6061WA00065 -
DC6061WA00064 - R0KBN3S
DC6061WA00064 -
DC6023LA034284 -
DC6038LA034272 -
As you can see, when the host doesn't respond because it's offline or can't be contacted for whatever reason, it moves on to the next one just as it should. But when one responds, it immediately writes another line with just the hostname and a dash.
I've tried making the write command to the output file as a separate subroutine call, I've tried removing the writing of the %%S variable to see if that was interfering in some way, I've tried saving the results to different variables before outputting them to the file, but nothing makes any difference.
I can clean up the resulting file without too much issue. I mostly just want to know what I'm missing that would be causing this to happen.
Any help or insight would be appreciated.
You will notice that when you run by itself:
wmic /node:somehostname bios get serialnumber
It still has Unicode cr/lf characters, which you cannot see on cmd prompt terminal as they are displayed as empty lines. This however causes the characters to be assigned to the %%C meta variable and run the loop again on these characters, will display both the entries in your file.. Instead, we check if a variable exists and create it if not, which will ensure we only assign the actual value. Note, we are using delayedexpansion here as we are setting and using variables inside of a code block.
#echo off
setlocal enabledelayedexpansion
set "list=C:\temp\input.txt"
type nul>"C:\Temp\output.txt"
for /F %%C in (%list%) do (
for /F "skip=1" %%S in ('wmic /node:%%C bios get serialnumber') do if not defined serial set "serial=%%C - %%S"
echo(!serial!>>"C:\temp\output.txt"
)
type output.txt
pause
Note
I created type nul>"C:\Temp\output.txt" to ensure we do not append to previous runs of the script, if you want it to append, then remove that line.
wmic.exe output is crippled with the unusual line ending cr/cr/lf,
resulting from an erroneous unicode conversion.
for /f would skip empty lines, but can't with those cr/cr/lf sequences
so these lines with just the %%C are output.
one solution is another for parsing the uppercase %%S with %%s
technically all the for /f are one line:
:: Q:\Test\2019\04\23\SO_55804785.cmd
#ECHO OFF
set "FileIn=c:\temp\input.txt"
set "FileOut=c:\temp\output.txt"
for /F "usebackq delims=" %%C in (
"%FileIn%"
) do for /F "skip=1 delims=" %%S in (
'wmic /node:%%C bios get serialnumber 2^>Nul ^|findstr "^." '
) do for /F "delims=" %%s in (
"%%S"
) do echo %%C - %%s >>"%FileOut%"
pause
I have a batch script that generates a file with the following structure (example)
123|etc|etc
345|etc|etc
678|etc|etc
I want my script to print out what it finds in each line, until it finds a |, so in this example i would want it to print:
123
345
678, and so on.
I've tried findstr /V with the | but it completely ignores the line (as the command states it will)
Any idea how could i turn this around?
#echo off
for /f "usebackq tokens=1 delims=|" %%a in ("test.txt") do (
echo %%a )
pause
This is looping through a file (test.txt) in the same directory as the batch script. I tell it to only use 1 token with a pipe delimiter then we just print out %%a which has the value of your first column of data.
i currently have this command for a batch file
for /F "skip=1 tokens=1 delims=\n" %i in (stats.txt) do echo %i
with the contents of stats.txt being
Title = Subaru's Great Rehab Strategy
URL = http://dynasty-scans.com/chapters/subarus_great_rehab_strategy
Tags = Subaru x Tsukasa[|]Yuri[|]
No. of Pages = 3
^ NOTE: the final line is actually blank
the idea of the line of code is to return the 2nd line with URL. the end goal would be that i would run this line in some sort of loop going though a series of ~12000+ stats.txt files and collecting all the URL lines into a single file
but when i run the command i get this
as you can see it has skipped the first line but it's cutting off where the n in dynasty and outputting the last 3 lines.
now if i remove delims=\n i get the same 3 lines but i don't get the first word before the space which seems to indicate that the value of delims is what splits a line into "tokens" which then i just grab the first one (and space must be the default)
when i go into notepad++, open the Find and Replace Dialog, turn Search Mode to extended and look for "\r\n" i get taken to the end of each line which is why i chose delims to be \n assuming this would then make the entire line one token
So my question is How can i get all of the 2nd line only of my stats.txt file?
The for /f loop already treats the carriage return and / or line feed as an end-of-line. No need to specify it as a delimiter. With delims=\n you're actually saying that all literal backslashes and letter n's should be treated as token delimiters. If you want the whole line, what you want is "skip=1 delims=".
Just out of habit, when reading the contents of a file with a for /f loop, I find it useful to enable usebackq just in case the filename / path contains a space or ampersand. That allows you to quote the filename to protect against such potential treachery.
#echo off
setlocal
for /F "usebackq skip=1 delims=" %%I in ("stats.txt") do if not defined URL set "URL=%%~I"
echo %URL%
Put into context, to use this to read many files named stats.txt and output the URLs into a single collection, enclose the whole thing in another for loop and enable delayed expansion.
#echo off
setlocal
>URLs.txt (
for /R %%N in ("*stats.txt") do (
for /F "usebackq skip=1 delims=" %%I in ("%%~fN") do (
if not defined URL set "URL=%%~I"
)
setlocal enabledelayedexpansion
echo(!URL!
endlocal
set "URL="
)
)
echo Done. The results are in URLs.txt.
If you want to strip the "URL = " from the beginning of each line and keep only the address, you could try changing your for /F parameters to "usebackq skip=1 tokens=3" if all the files follow the same format of URLSpace=Spacehttp://etc.. If you can't depend on that, or if any of the URLs might contain unencoded spaces, you could also change echo(!URL! to echo(!URL:*http=http!
You don't need to use a FOR /F loop, you can also read it with a SET /P
setlocal EnableDelayedExpansion
< stats.txt (
set /p line1=
set /p URL_Line=
)
echo(!URL_Line!
Try this from the command line:
(for /F "tokens=1* delims=:" %i in ('findstr "URL" stats*.txt') do echo %j) > output.txt
the idea ... is to return the 2nd line with URL
If you want to insert this line in a Batch file, just double the percent signs.
Try this from the prompt:
(for /f "tokens=1*delims=]" %a in ('find /v /n "" *.csv^|findstr /l /b "[2]"') do #echo %b)>u:\r1.txt
Where - I used *.csv for testing (substitute your own filemask) and I used u:\r1.txt for the result - substitute as seems fit (but don't output to a file tat fits your selected filemask !)
It works by prefixing each line in each file with a bracketed number [n] (find - /n=and number /v lines that do not match "" - an empty string); then selecting those lines that /l - literally /b at the beginning of the line match "[2]".
The result is all of the second-lines of the files, preceded by the literal "[2]". All we need to do then is tokenise the result, first token up to delimiter "]" will be "[2" assgned to %%a and remainder-of line (token *) will be assigned to %%b
Have you tried
for /F "skip=1 tokens=1 delims=\n" %i in (stats.txt) do echo %i && goto :eof
I haven't tested it as I don't have access to a Windows machine at the moment, but that should exit the for-loop after the first iteration, which is what you want.
Okay I have several lines in a text file. I want to get the first line and save it in another file. For example this is the text file:
put returns between paragraphs
for linebreak add 2 spaces at end
for linebreak add 2 spaces at end2
for linebreak add 2 spaces at end3
I want put returns between paragraphs to be saved into another file.
I used
for /f "tokens=" %%A in ('findstr /r "^[0-9][0-9]*$" <"C:\Users\Sherlock\Desktop\AbcImport\123.txt"') do echo 123>>1234.txt
pause
But it doesn't work at all.
How to get just the first line of a text file written into a new text file using a batch file?
Option 1 - SET /P : This is the simplest and fastest pure batch solution, provided the line does not exceed 1021 bytes, and it does not end with control characters that must be preserved. The size of the file does not matter - it will always read and write the first line very quickly.
#echo off
setlocal enableDelayedExpansion
set "ln="
<"input.txt" set /p "ln="
>"output.txt" (echo(!ln!)
Option 2 - FOR /F : This will work with lines up to ~8191 bytes long, but it can be slow if the file is really large because the FOR /F loop must read the entire file before it processes the first line. This solution is basically the same as the Mofi answer, except it disables the EOL option, so it never ignores the first line, regardless what the first character is. It does have a limitation that it will skip empty lines, so technically it does not give the correct result if the first line is empty:
#echo off
for /f usebackq^ delims^=^ eol^= %%A in ("input.txt") do echo(%%A>"output.txt"&goto :break
:break
There is a way to preserve the first line if it is empty using pure batch, but I would not bother. I would move on to ...
Option 3 - JREPL.BAT, or some other non-batch solution : Batch is quite poor at manipulating text files. You are much better off using some other scripting language like VBScript, JScript, or Powershell. Or a Windows port of any number of unix utilities.
I would use JREPL.BAT - a hybrid JScrpit/batch regular expression text processing utility that runs natively on any Windows machine from XP onward. It is way overkill for such a simple task, but it is an extremely handy, powerful, and efficient tool to have in your arsenal. Once you have it, then it can be used for many text processing tasks. Full documentation is embedded within the script.
jrepl "^.*" "$&" /jendln "quit=true" /f "input.txt" /o "output.txt"
Use CALL JREPL if you put the command within a batch script.
Here is the batch code to write just first non blank/empty line of a text file into another text file.
#echo off
for /F "usebackq delims=" %%I in ("InputTextFile.txt") do (
echo %%I>"OutputTextFile.txt"
goto ContinueAfterLoop
)
:ContinueAfterLoop
InputTextFile.txt is the file in current directory containing the first line to copy.
OutputTextFile.txt is the file created in current directory with first line from input file copied into this output file.
The command GOTO is used to exit the loop after first line is processed and continue the batch file below the loop.
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 /?
goto /?
Read also the Microsoft article about Using Command Redirection Operators.
You can use use this command:
SetLocal EnableDelayedExpansion
for /f "tokens=* delims=;" %%m in ("C:\Users\Sherlock\Desktop\AbcImport\123.txt") do (
set /p FirstLine=<%%m
echo !FirstLine!>>1234.txt
)
and for multiple file:
SetLocal EnableDelayedExpansion
for %%a in ("*") do (
for /f "tokens=* delims=;" %%m in ("%%a") do (
set /p FirstLine=<%%m
echo !FirstLine!>>1234.txt
)
)
rem Get the first line of a text file:
set /P "line=" < "C:\Users\Sherlock\Desktop\AbcImport\123.txt"
rem Write it into a new text file:
echo %line%> 1234.txt
I have a log file containing a stack trace split over a number of lines. I need to read this file into a batch file and remove all of the lines breaks.
As a first step, I tried this:
if exist "%log_dir%\Log.log" (
for /F "tokens=*" %%a in ("%log_dir%\Log.log") do #echo %%a
)
My expectation was that this would echo out each line of the log file. I was then planning to concatenate these lines together and set that value in a variable.
However, this code doesn't do what I would expect. I have tried changing the value of the options for delims and tokens, but the only output I can get is the absolute path to the log file and nothing from the contents of this file.
How can I set a variable to be equal to the lines of text in a file with the line breaks removed?
If you want to use quotes for your filename in the FOR/F loop you need to add the usebackq option too, else you get a string not the content of your file.
for /F "usebackq delims=" %%a in ("%log_dir%\Log.log") do #echo %%a
Or remove the quotes
if exist "%log_dir%\Log.log" (
for /F "tokens=*" %%a in (%log_dir%\Log.log) do #echo %%a
)