0

i have a batch script which i use to merge all the same name txt files from directories & subdirectories into one, here's my code:

@echo off
for /f "tokens=*" %%a in (textfilenames.txt) do (
    for /D /R %%I in (%%a.txt) do (
    type "%%I" >> merged.tmp
    echo. >> merged.tmp
    )
    ren merged.tmp All_Combined_%%a.txt
  )
)
@pause

and so when the loop doesn't finds the file on some directories then this msg is displayed:

The system cannot find the file specified. 
The system cannot find the file specified.
The system cannot find the file specified.
Press any key to continue . . .

and i wanna hide above error and so i used >NUL in file name eg:

@echo off
for /f "tokens=*" %%a in (textfilenames.txt) do (
    for /D /R %%I in ('%%a.txt^>NUL') do (
    type "%%I" >> merged.tmp
    echo. >> merged.tmp
    )
    ren merged.tmp All_Combined_%%a.txt
  )
)
@pause

but i'm still getting error msg, i want to make this script completely silent like no error nothing or if somehow it's not possible then i wann customize the error to something like:

The system cannot find the example.txt specified. in the \Subfolder\Enigma\

etc!

Vicky Malhotra
  • 340
  • 1
  • 4
  • 13
  • 1
    Insert left to first `for` the condition `if exist "textfilenames.txt"` and modify completely wrong `for /D /R %%I in ('%%a.txt^>NUL') do (` to `for /R %%I in ("%%a.txt*") do (` or even better `for /F "delims=" %%I in ('dir "%%a.txt" /A-D /B /S 2^>nul') do (`. I recommend also __not__ using `a` as loop variable for the outer __FOR__ loop although working here. The chapter __Issue 7: Usage of letters ADFNPSTXZadfnpstxz as loop variable__ in [this answer](https://stackoverflow.com/a/60686543/3074564) explains the reason. – Mofi Nov 09 '20 at 08:18
  • 1
    Best for the second __FOR__ loop would be `for /F "delims=" %%I in ('%SystemRoot%\System32\where.exe /R . "%%a.txt" 2^>nul') do (` as `where` ignores short file names which by chance match also the long file name in comparison to internal command `dir`. That is very unlikely here in this case, but `where` searches really just for files of which long file name matches the specified string. BTW: Should the batch file always work with the files in directory of the batch file or on current directory as coded at the moment? Current directory and batch file directory can be different. – Mofi Nov 09 '20 at 08:25
  • 1
    I recommend further to read DosTips forum topic: [ECHO. FAILS to give text or blank line - Instead use ECHO/](https://www.dostips.com/forum/viewtopic.php?f=3&t=774). The command line `echo. >> merged.tmp` can fail in rare cases to output an empty line. Well, in real this line outputs a line with a space character and not an empty line. So the file `merged.tmp` contains lines with a single space. Better would be `echo(>>merged.tmp` which always works and results in appending really an empty line to the file. – Mofi Nov 09 '20 at 08:28
  • 1
    Last hints: The second line of this batch file should be `del /F merged.tmp 2>nul` to make sure there is no deletable file `merged.tmp` in current directory on starting this batch file, for example on having last time stopped the batch file processing in the middle. The __FOR__ option `"tokens=*"` resulting in removing leading spaces/tabs from non-empty lines read from `textfilenames.txt` and ignoring lines starting with `;` should be modified to `"eol=| delims="` as file names can start with one or more spaces and can have also a semicolon at beginning of file name. – Mofi Nov 09 '20 at 08:35
  • 1
    `delims=` disables line splitting behavior completely by definition of an empty list of string delimiters and so file names with spaces at beginning are correct processed. `eol=|` defines a character as end of line character which no file name can have ever and so file names with `;` at beginning are correct processed. It would be also possible to use `eol=?` or `eol=*` or use `delims^=^ eol^=` without surrounding double quotes to specify an empty list of string delimiters and no end of line character to process all non-empty lines in `textfilenames.txt` without any modification by __FOR__. – Mofi Nov 09 '20 at 08:39
  • 1
    I forgot to write what is wrong with `for /D /R %%I in (%%a.txt) do (`. Open a [command prompt](https://www.howtogeek.com/235101/), run `cd /D "%UserProfile%"`, next `for /D /R %I in (test.txt) do @echo %I`, and look on output. As `test.txt` contains neither `*` nor `?`, `for` searches recursive for __directories__ and assigns each directory path with `test.txt` appended to loop variable. It does not search recursive for __file__ `test.txt` as expected by you as done by command `dir` with the used options or command `where` with the used options in my first two comments. – Mofi Nov 09 '20 at 08:49
  • As i'm new to batch scripting so for simplifed understanding i just removed `/d` from 2nd loop and it's not displaying any error now and i just work with few texts so it's working fine for me, thanks for the well explained ideas :) – Vicky Malhotra Nov 09 '20 at 10:49
  • A `for [/D] [/R]` loop only checks the file system when the item behind `in` contains a wildcard like `?` or `*`; so without such, use `if exist` to check for existence… – aschipfl Nov 09 '20 at 13:03

1 Answers1

1

If you do it right, you do not need to hide anything.

In this example we use the dir command with the /s function to search for files. It will not complain about files not found because it does not expect the file exist indefinitely in any given directory, it simply searches for it:

@echo off
for /f "useback delims=" %%a in ("textfilenames.txt") do (
   for /f "delims=" %%I in ('dir /b/s/a-d "%%a.txt"') do (
    (type "%%I"
     echo()>>All_Combined_%%a.txt
    )
  )
)
@pause

Note, I eliminated the ren part as that is not needed. You can write to the combined file in the loop.

I also use echo( instead of echo. for reasons that can be found on numerous answers in SO.

Lastly, we can eliminate one parenthesized code block, by putting the second for loop inline with the first:

@echo off
for /f "useback delims=" %%a in ("textfilenames.txt") do for /f "delims=" %%I in ('dir /b/s/a-d "%%a.txt"') do (
    (type "%%I"
     echo()>>All_Combined_%%a.txt
  )
)
@pause
Gerhard
  • 22,678
  • 7
  • 27
  • 43