I use this batch files to create a list of files
#echo off
(for /f "delims=" %%a in ('dir/b/a-d *.tex') do echo %%a,)>liste.dat
the result is like this
file1.tex,
file2.tex,
file3.tex,
...
lastfile.tex,
how do I delete the last comma?
#echo off
SETLOCAL EnableDelayedExpansion
SET "in="
(
for %%a in (*.tex) do (
IF "!in!"=="" (
set in=%%a
) ELSE (
echo !in!,
set in=%%a
)
)
echo !in!
)>liste.dat
#echo off
setlocal EnableDelayedExpansion
set "comma="
< NUL (
for %%a in (*.tex) do (
set /P "=!comma!%%a"
set comma=,^
%Empty line%
)
echo/
) > liste.dat
EDIT: Reply to a comment
Ops! When I was developing this code I just displayed the output in the screen, where it looks correct:
C:\> test.bat
One.tex,
Three.tex,
Two.tex
Even if the output is sent to a file and the file is displayed in the screen, the output looks correct:
C:\> test.bat > output.txt
C:\> type output.txt
One.tex,
Three.tex,
Two.tex
However, the character inserted after each comma is just a LF so if this file is open with Notepad, the LF's are not converted to "end of lines"; just cmd.exe screen output converts LF to CR+LF pair ("cooked output" instead of "raw output").
The way to fix this detail is inserting a complete CR+LF pair after each comma:
#echo off
setlocal EnableDelayedExpansion
for /F %%a in ('copy /Z "%~F0" NUL') do set "CR=%%a"
set "comma="
< NUL (
for %%a in (*.tex) do (
set /P "=!comma!%%a"
set comma=,!CR!^
%Empty line%
)
echo/
) > liste.dat
The problem is that you don't know how many lines/files there will be. So you'll have to use two loops the way your code is written. One to count the lines and one to perform the operations. It's way easier to have a different handling for the first line instead of the last one. So how about this:
#echo off
SETLOCAL EnableDelayedExpansion
SET /a i=0
(for /f "delims=" %%a in ('dir /b/a-d *.tex') do (
IF !i!==1 (
echo ,%%a
) ELSE (
ECHO %%a
SET /a i=1
)
)
)>liste.txt
This will generate something like this:
file1.tex
,file2.tex
,file3.tex
...
,lastfile.tex
This seems equivalent to your desired output. If you actually want to have , at the end of the lines instead of at the beginning of the next one, tell me and I'll update the code but it'll be quite ugly.
Related
My arqtext.txt has the following dataset:
A,B,C,
(123 or 456) and (789 or 012),1,5,
(456 or 654) and (423 or 947),3,6,
(283 or 335) and (288 or 552),2,56,
I want to change the 1st column of the last 3 rows to a new string set in the script, with the result like:
A,B,C,
roi1,1,5,
roi2,3,6,
roi3,2,56,
But my code only output the header "A,B,C,":
#echo off
setlocal EnableDelayedExpansion EnableExtensions
set roi1="(123 or 456) and (789 or 012)"
set roi2="(456 or 654) and (423 or 947)"
set roi3="(283 or 335) and (288 or 552)"
set /p "header="<"arqtext.txt"
echo %header%>arqtextnovo.txt
for /f "skip=1 tokens=1,* delims=," %%a in ("arqtext.txt") do (
if %%a=="roi1" (
echo roi1,%%b>>arqtextnovo.txt
)
if %%a=="roi2" (
echo roi2,%%b>>arqtextnovo.txt
)
if %%a=="roi3" (
echo roi3,%%b>>arqtextnovo.txt
)
)
rem EXIT /B
pause>nul
This is the way I would do it:
#echo off
setlocal EnableDelayedExpansion
set "roi[(123 or 456) and (789 or 012)]=1"
set "roi[(456 or 654) and (423 or 947)]=2"
set "roi[(283 or 335) and (288 or 552)]=3"
set /P "header=" < "arqtext.txt"
> arqtextnovo.txt (
echo %header%
for /f "usebackq skip=1 tokens=1,* delims=," %%a in ("arqtext.txt") do (
echo roi!roi[%%a]!,%%b
)
)
rem EXIT /B
pause>nul
The for /F command requires "usebackq" option if the filename is enclosed in quotes. Otherwise, it process the literal string enclosed in quotes.
It is more efficient to (redirect the whole output) > to a file, instead of append >> every new line. This also avoid the problems of redirect lines that ends in numbers.
If you have several values and want to select a result value based on the first one, it is much simpler and more efficient to use an array instead of test each individual value.
Let's suppose this method:
set /P "selector=Enter selector: "
if "%selector%" equ "nine" set result=9
if "%selector%" equ "seven" set result=7
if "%selector%" equ "five" set result=5
Instead, you may define an array called "value":
set "value[nine]=9"
set "value[seven]=7"
set "value[five]=5"
... and then directly get the result value this way:
set "result=!value[%selector%]!"
The same method is used in this code. However, you have not specified what happen if the input value is not one of the array elements.
For a further description on array management in Batch files, see this answer
I have a text file that I would like to edit and therefore would like to remove the last line. I have the following code for this:
for /f "delims=" %%a in (input.txt) do (
echo/|set /p ="%%a%"
)>>output.txt
input:
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
output:
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
Now I would like to edit the data in groups for example by the first value, so that I have the following output:
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
If I replace the FOR /F "delims=" %%a in (input.txt) do … loop with an equivalent FOR %%a in … loop:
#ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
set "_gruppeName="
(
for %%a in (
"GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
) do (
for /f "tokens=1 delims=;" %%A in ("%%~a") do (
if /I NOT "%%~A"=="!_gruppeName!" (
if defined _gruppeName echo(
set "_gruppeName=%%~A"
)
)
echo/|set /p ="%%~a"
)
echo(
)>>output.txt
REM debugging output follows
type output.txt
Output:
1st run: 2>NUL del output.txt & D:\bat\CR\61816520.bat
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
Next run: D:\bat\CR\61816520.bat
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
Your question is not clear
based on ... the first value (GRUPPEA)
is it SORTed? or just write duplicates on the same line?
#echo off
SETLOCAL EnableExtensions EnableDelayedExpansion
::VARIABLES
set "in=input.txt" IN file
set "out=output.txt" OUT file
set/a"#lines=0"
set "gruppe="
set "prevContent="
::Count lines
FOR /F %%L in ('
"findstr /N "^^" "%in%" %= do not skip empty lines =%"
') do set/a"#lines+=1" %= Get the # of lines =%
::Read IN via SET /P #LINES number of times
::Bangs (!) will be lost
<"%in%" >"%out%" (FOR /L %%# in (1 1 %#lines%) do (
set "data=" ::clear DATA
set/p"data=" ::read from IN
FOR /F tokens^=1^ delims^=^;^ eol^= %%T in ("!data!") do set "gruppe=%%T"
if NOT "!prevContent!" == "!gruppe!" (
set "prevContent=!gruppe!"
echo(
)
<nul set/p"=!data!" ::does not work with leading space, tabs, or equal signs
)) %= read file by lines via SET /P =%
exit /b
The script counts the number of lines using FINDSTR /N and a FOR /F loop to count the # of lines, which is required to execute SET /P that many times.
Tips:
Use ECHO( instead of the problematic ECHO.
Using a pipe | is very slow, as described by #jeb here. Use <nul instead
I'm using this code to set some data into array but, i'm stuck on echoing the last one who has this character "?"
So; my question is how can i escape this kind of character "?" to echo the last item like "Hackoo?"
#echo off
setlocal enabledelayedexpansion
set i=0
for %%a in ("1" "2" "223231" "AAA" "Hello^ | World" "(Hello^)(World^)" "Hackoo^?") do (
set /a i+=1
set Line[!i!]="%%~a"
)
set Line
pause
Using FOR without any switch the CMD will try to get a path if your using the special char ?.
A solution is the substitution if you can't use any other switch (like : /F) :
#echo off
setlocal enabledelayedexpansion
set $List="1" "2" "223231" "AAA" "Hello | World" "(Hello)(World)" "Hackoo ?"
set $List=%$List:?=#%
set i=0
for %%a in (%$List%) do (
set /a i+=1
set "$Tmp=%%a"
set "Line[!i!]=!$Tmp:#=?!"
)
set Line
pause
#echo off
for /f "tokens=1-4" %%a in ("? * ; %%") do (
echo %%a
echo %%b
echo %%c
echo %%d
)
pause
my input file named done.txt as per below.
clip_id HCQLR01HM01AO
clip_id HAUGL01HM01AC
clip_id HEBQC01HM01CD
clip_id HEFCD01HM01AK
clip_id HBYVA01HM01CY
clip_id HCFJI01HM01AI
And i want to extract last 12 char and write into new text file with name res.txt
this is my coding. but this only works for 1st line. How to loop it for 2nd,3rd and 4th lines?
#echo off
setlocal enabledelayedexpansion
for /f "tokens=*" %%a in (C:\Users\administrator\Desktop\com\done.txt) do (
set line=%%a
set chars=!line:~-13,12!
echo !chars! > res.txt
)
pause
many thanks
The single ">" in echo !chars! > res.txt overwrites res.txt each time. Change this line to echo !chars! >> res.txt
You might also want to remove res.txt before the loop, resulting in:
#echo off
setlocal enabledelayedexpansion
del res.txt
for /f "tokens=*" %%a in (C:\Users\administrator\Desktop\com\done.txt) do (
set line=%%a
set chars=!line:~-13,12!
echo !chars! >> res.txt
)
pause
I want to write a batch script which reads each line of a file. Sounds easy but the problem is that not every line has the same amount of tokens. The next thing is that every token is seperated from each other with a delimiter which I don't want to have in my output.
Here is a example of the file:
string1|string2|string3|string4
string1|||string4
When I'm reading that file, every token has to be on its right place. What I mean is when I'm reading the second line the output must be:
string1 empty empty string4
thanks for help
gawk for Windows can do the job:
awk -F"|" "{for (i=1;i<=NF;i++) $i=$i?$i:\"empty\"};7" file.in>file.out
#ECHO OFF
SETLOCAL
(
FOR /f "delims=" %%a IN (q21551753.txt) DO (
SET line=%%a
SETLOCAL ENABLEDELAYEDEXPANSION
SET line=!line:^|= ^|!
ECHO(!line!
endlocal
)
)>tempfile.txt
SET "spaces= "
FOR /f "tokens=1-7delims=|" %%a IN (tempfile.txt) DO (
SET "$a=%%a%spaces%"
SET "$b=%%b%spaces%"
SET "$c=%%c%spaces%"
SET "$d=%%d%spaces%"
SET "$e=%%e%spaces%"
SET "$f=%%f%spaces%"
SET "$g=%%g%spaces%"
SETLOCAL ENABLEDELAYEDEXPANSION
ECHO(!$a:~0,8!!$b:~0,9!!$c:~0,8!!$d:~0,8!!$e:~0,9!!$f:~0,5!!$g:~0,6!
endlocal
)
GOTO :EOF
I used a file named q21551753.txt for my testing.
string1|string2|string3|string4
string1|||string4
|string2||string4|string5|string6
%one%|!2!||"three"|^four^|string6
Response:
string1 string2 string3 string4
string1 string4
string2 string4 string5 strin
%one% !2! "three" ^four^ strin
Note that the column-widths are defined in the ECHO(!$a... statement - your choice of the number and width of each column. Note that spaces is set to a bunch of spaces.
tempfile.txt is created. Whether you delete this, where it is created and what you call it are all up to you.
The following assumes data does not contain !, and no line begins with ;. These restrictions can be eliminated with more code.
The key trick is to use variable expansion search and replace to convert str1|str2|str3|str4 into "str1"|"str2"|"str3"|"str4". Then a second FOR /F can safely parse the tokens, even when the value is missing. The values you want are in %%~A, %%~B, %%~C, and %%~D. The line I ECHO is just to demonstrate the values of each token.
#echo off
setlocal enableDelayedExpansion
for /f "delims=" %%L in (test.txt) do (
set "ln=%%L"
set "ln="!ln:^|="|"!""
for /f "tokens=1-4 delims=|" %%A in ("!ln!") do (
echo A=%%~A B=%%~B C=%%~C D=%%~D
)
)
Thanks for your answers.
But I found out that I had another problem. The count of the tokens are not always the same and the count is often about 20-40 tokens at one line.
I created a solution with a sub-procedure:
#echo off
setlocal enabledelayedexpansion
for /f "tokens=*" %%a in (Book1.csv) DO (
set "work=%%a"
for /l %%i in (1,1,2) do set "work=!work:||=|NULL|!"
set "line=!work!"
call :processToken
)
goto eof
:processToken
for /F "tokens=1* delims=|" %%x in ("!line!") do (
echo %%x
set line=%%y
)
if not "!line!" == "" goto :processToken
goto :eof
:eof