What your code does is:
concatenate every .txt
file and number each line
tokenise to line number in %%a
and line contents in %%b
echo
an empty line into findstr
and attempt to find the numbers, discarding the result
If the line number was not found, echo
the line contents
then attempt to write any output to the filename.
So - there's no need to try to fit all of this on one line - here's the more conventional layout:
@echo off
(
for /f "tokens=1,* delims=[]" %%a in ('type *.txt^|find /v /n ""') do (
echo/|findstr /x "34 35 36 37 38 39 40 41 42 43 80 81 82 83 84 85 86 87 88 89" >nul || echo/%%b
)
)>%%~na-edit.txt
Since %%a
is outside of the for
loop, %%a
is not in-context, so %%~na-edit.txt
is parsed as %%
=>%
and the remaining characters have no special meaning, hence %~na-edit.txt
.
Even had the apparent intention worked, %%a
is the line number, not the filename.
Further, since there is no &
to separate @echo off
from the remainder, the effective code is
@echo off>%%~na-edit.txt
since anything beyond off
is discarded.
The resultant output of the find
would be
[1]line 1 of file 1
…
[41]line 41 of file 1
[42]line 1 of file 2
…
Here's an UNTESTED idea
@echo off
setlocal
for /f "delims=" %%e in ('dir /b /a-d *.txt') do (
(
for /f "tokens=1*delims=[]" %%b in ('find /v /n "" ^<"%%e"') do (
echo %%b|findstr /x "34 35 36 37 38 39 40 41 42 43 80 81 82 83 84 85 86 87 88 89">nul||echo/%%c
)
)>"%%~ne-edit.txt"
)
Note again this is UNTESTED
To explain:
It's normal to insert a setlocal
flavour to ensure the environment is not corrupted by executing the batch.
Perform a dir
command to list the directory of *.txt
files in /b
basic form (names only) /a-d
without directory names.
This builds a list of filenames in memory, each is assigned to %%e
in turn, so the source filename is in %%e
. The delims=
ensures the entire filename is assigned to %%e
, even if it contains a separator like Space. Also, this list is built before the output files are generated, so the output filenames will not be included in the list (but would be if type *.txt
was used)
Number each line in the file %%e
, and tokenise to %%b
and %%c
using []
. File is read using ^<
else the filename will be reported by find
before the listing of the numbered lines. The redirector needs to be escaped so that cmd
assigns it to the find
command instead of the for
(which would generate a syntax error).
echo
the line number in %%b
to the findstr and if there's no exact match, echo
the line contents. Although %%c
will never be empty (which would be for an empty source line in this case & for /f
skips empty lines), the echo/
variant of echo
would generate an empty line instead of an echo
status report.
Note that the syntax
(
for…(
…
)
)>"filename"
will gather the output between the first (
and last )
and create a new file
The filename is quoted to ensure that filenames containing separators are correctly processed.
I prefer to avoid ADFNPSTXZ (in either case) as metavariables (loop-control variables)
ADFNPSTXZ are also metavariable-modifiers which can lead to difficult-to-find bugs
(See `for/f` from the prompt for documentation)
Note that should a filename whatever-edit.txt
exist when this batch is executed, a file whatever-edit-edit.txt
will likely appear.