Reputation: 372
I have a few log files that my batch script needs to be able to read and parse.
I've run into a bit of a problem, where my FOR loop can read most files, but cannot read a specific one. If I run in a command prompt window
for /f %Z in (N151204.log) do echo %Z
it works great, but exactly the same syntax on a different file:
for /f %Z in (IN151205.log) do echo %Z
Gives me:
The system cannot find the file IN151205.log.
I can read file IN151205.log
with
more IN151205.log
without a problem. So it doesn't seem to be a permissions issue, or read-locked as far as I can tell.
Why is the for loop having issues with this particular file?
Upvotes: 2
Views: 639
Reputation: 49086
The error message of command FOR is caused by the fact that FOR command opens a file for reading always using CreateFile with FILE_SHARE_READ
AND FILE_SHARE_DELETE
.
The log file IN151205.log
is obviously written at the moment by another application with having a write lock established on the file. The file access by command FOR fails therefore with a sharing violation because of FILE_SHARE_DELETE
.
MORE has success to open the file with write lock set and outputs the lines as it really only reads the file and using a different method. MORE uses CreateFileMapping using PAGE_READWRITE
to read and output the file contents page wise which works completely different than CreateFile
and can be used also on files currently locked by another application as mentioned in Remarks section with:
It is not required, but it is recommended that files you intend to map be opened for exclusive access.
PAGE_READWRITE
allows also read access on a file currently allowing only read access according to sharing mode.
See also the Microsoft documentations Generic Access Rights and File Security and Access Rights.
The error message output by FOR on access to a file fails because of a sharing violation is obviously not good as being misleading for users.
EDIT:
Reading a write-locked file from within a batch file line by line with ignoring empty lines can be done with
for /F delims^=^ eol^= %%I in ('more IN151205.log') do echo(%%I
and with
for /F delims^=^ eol^= %%I in ('type IN151205.log') do echo(%%I
Thanks Aacini and Squashman for this additional information.
Upvotes: 8