cmd - How to read a text file in bottom up manner using batch -
i working on project requires creation of resources, while creating resources write in file rollback creation process if error occurs. there catch in here, resources has deleted in opposite manner in created, when write in roll file :
delete r1 delete r2 .. .. delete rn
i want delete resources in order ->
delete rn delete rn-1 .... ... delete r1
is there way in windows batch ?
there no native way read file in reverse order using batch.
but, while not fastest method, can solved reading file in normal order, prefixing each line padded number, sorting list in reverse order, splitting line separate numbers , process list
@echo off setlocal enableextensions disabledelayedexpansion set "file=data.txt" /f "tokens=1,* delims=¬" %%a in (' cmd /v:off /e /q /c"set "counter^=10000000" & /f usebackq^ delims^=^ eol^= %%c in ("%file%") (set /a "counter+^=1" & echo(¬%%c)" ^| sort /r ') ( echo %%b )
how works:
the code will, each line in input file, output number prefix , line, delimiter (¬
) later able separate both elements.
as later data sorted, need prefix has uniform length. initialize counter in 10000000
, increase prefix in lines has same length (note: if file has more 99999999 lines, please, don't use method)
to change counter use set /a "counter+=1"
, echo inside loop need delayed expansion, generate problems data readed file (i don't know if can contain !
characters).
we can enable/disable delayed expansion handle it, necessary each line, there performance loss. solve it, code executed in separate cmd
instance.
why separate instance? code in separate instance executed not in batch context, in command line context. in command line context set /a
command echoes result of calc, don't need , delayed expansion problem vanishes. calculate new counter (that gets echoed), , echo delimiter , line readed input file. have following code
set "counter=10000000" /f usebackq^ delims^=^ eol^= %%c in ("%file%") ( set /a "counter+=1" echo(¬%%c )
it written concatenated command , passed argument cmd
instance (note: ^
used escape problematic characters), executed echo off
(/q
), extensions enabled (/e
) , disabled delayed expansion (/v:off
)
cmd /v:off /e /q /c"set "counter^=10000000" & /f usebackq^ delims^=^ eol^= %%c in ("%file%") (set /a "counter+^=1" & echo(¬%%c)"
this generate prefixed output. now, sort in reverse order, output piped sort /r
command.
cmd /c"..." | sort /r
as result of pipe needs processed (in sample echo
line console), full pipe executed inside for /f %%a
(more ^
escape characters).
/f "tokens=1,* delims=¬" %%a in (' cmd /c"..." ^| sort /r ') ....
this for
command indicates ¬
character used delimiter tokenize input lines (the result of pipe execution), , want retrieve first token (the number prefix, not used needs included) %%a
, rest of line (without additional splitting) in %%b
.
so, @ end, code in do
clause of for /f %%a
executed each line in input file, in reverse order, line stored in %%b
.