www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Careful when using chdir inside a dirEntries loop

reply Andrej Mitrovic <none none.none> writes:
Here's a little buggy code which most often throws an exception:

    foreach (string entry; dirEntries(curdir, SpanMode.shallow))
    {
        if (entry.isdir)
        {
            foreach (string subentry; dirEntries(entry, SpanMode.shallow))
            {
                if (subentry.isdir)
                {
                    chdir(rel2abs(subentry));
                }
            }
        }
    }

Usually throws something like:
std.file.FileException std\file.d(1124): .\foo\bar.d: The system cannot find
the path specified.

The problem is, chdir will modify curdir and dirEntries doesn't store 'curdir'
internally as an absolute address.

The way to work around this is to call rel2abs as soon as possible when using
'curdir' (the first line changed):

    foreach (string entry; dirEntries(rel2abs(curdir), SpanMode.shallow))
    {
        if (entry.isdir)
        {
            foreach (string subentry; dirEntries(entry, SpanMode.shallow))
            {
                if (subentry.isdir)
                {
                    chdir(rel2abs(subentry));
                }
            }
        }
    }

I've had a use for code like this because where I was invoking a batch file
which was always relative to the current subdirectory. But anyways, I just
thought I'd throw it out in case anyone else runs into this.
Jun 09 2011
next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-09 15:20, Andrej Mitrovic wrote:
 Here's a little buggy code which most often throws an exception:
 
 foreach (string entry; dirEntries(curdir, SpanMode.shallow))
 {
 if (entry.isdir)
 {
 foreach (string subentry; dirEntries(entry, SpanMode.shallow))
 {
 if (subentry.isdir)
 {
 chdir(rel2abs(subentry));
 }
 }
 }
 }
 
 Usually throws something like:
 std.file.FileException std\file.d(1124): .\foo\bar.d: The system cannot
 find the path specified.
 
 The problem is, chdir will modify curdir and dirEntries doesn't store
 'curdir' internally as an absolute address.
 
 The way to work around this is to call rel2abs as soon as possible when
 using 'curdir' (the first line changed):
 
 foreach (string entry; dirEntries(rel2abs(curdir), SpanMode.shallow))
 {
 if (entry.isdir)
 {
 foreach (string subentry; dirEntries(entry, SpanMode.shallow))
 {
 if (subentry.isdir)
 {
 chdir(rel2abs(subentry));
 }
 }
 }
 }
 
 I've had a use for code like this because where I was invoking a batch file
 which was always relative to the current subdirectory. But anyways, I just
 thought I'd throw it out in case anyone else runs into this.

I'm not sure if that's a valid bug or not. It could easily be a case of "just don't do that," or it could be that dirEntries needs to be improved. Open a bug report on it so that it's at least recorded and known. Then we can decide the best course of action to take with it. - Jonathan M Davis
Jun 09 2011
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Ok filed. I don't know whether it's a bug or not, I do think it's a
subtle issue worth investigating though.
Jun 09 2011