3

I have a situation where I need to run a "pre-check" to see if a directory is "createable". This is not a problem, just run a file.mkdirs() and see if it returns true.

The problem is that I would like to clean up after this check. This is a bit tricky, because I want to delete only those folders and subfolder that mkdirs() actually created.

Can anyone think of a clever way to do this?

tostao
  • 2,803
  • 4
  • 38
  • 61
user1283068
  • 1,694
  • 4
  • 15
  • 25
  • 6
    Isn't it easier to combine File.exists(), File.isDirectory() and File.canWrite(), rather than figuring out how to undo effects of mkdirs()? – david a. Apr 09 '13 at 14:14

5 Answers5

2

I think this method does the job without you having to call mkdirs:

public static boolean canMkdirs(File dir) {
    if(dir == null || dir.exists())
        return false;
    File parent = null;
    try {
        parent = dir.getCanonicalFile().getParentFile();
        while(!parent.exists())
            parent = parent.getParentFile();
    } catch(NullPointerException | IOException e) {
        return false;
    }
    return parent.isDirectory() && parent.canWrite();
}
Lone nebula
  • 4,768
  • 2
  • 16
  • 16
  • 1
    I like this approach, because there is no cleanup afterwards. It works on the presumption that if you have write access to a directory, you will be able to create the required subdirectories under that directory. It is, however, not a test that is 100% effective. Consider path names containing invalid characters, or a path which breaks the total length allowable by the OS or the underlying file system. Those things are not checked by the method above. But it's close enough for my needs. Thanks a lot! – user1283068 Apr 10 '13 at 08:54
0

Keep one array which holds name of that dirs. so when you want to delete dir you can take that array content/string/dir-name to delete.

AmitG
  • 10,365
  • 5
  • 31
  • 52
0

A bit dangerous:

if (file.mkdirs()) {
    long t0 = file.lastModified();
    for (;;) {
        long t = file.lastModified();
        if (t < t0 - 1000L) { // Created longer than it's child minus 1 s?
            break;
        }
        t0 = t;
        file.delete();
        file = file.getParentFile();
    }
}
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
0

If my assumption that permissions are inherited in the file structure is correct, something like this should do it:

File f = new File("C:\\doesntExist\\Nope\\notHere");
File tempFile = f;
while (!tempFile.exists())
   tempFile = tempFile.getParentFile();
if (!tempFile.canWrite()
    && tempFile.isDirectory()) // Copied this line from Lone nebula's answer (don't tell anyone, ok?)
   System.out.println("Can't write!");
else
{
   f.mkdirs();
   ...
}
Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138
0

Judging by the mkdirs() source code:

public boolean mkdirs() {
       if (exists()) {
           return false;
        }
        if (mkdir()) {
            return true;
       }
       File canonFile = null;
       try {
            canonFile = getCanonicalFile();
        } catch (IOException e) {
            return false;
        }

        File parent = canonFile.getParentFile();
        return (parent != null && (parent.mkdirs() || parent.exists()) &&
                canonFile.mkdir());
    }

If I hadn't missed something you have two options:

  • remeber the state of the files on the disk before calling the mkdirs(), compare it with the state after the mkdirs(), handle if necessary
  • extend the File class and override mkdirs() method to remember exactly which files were created. If any are created, handle them.

The latter seems like a more elegant solution which will yield less code.

UPDATE:

I strongly recommend to take in consideration david a. comment.

linski
  • 5,046
  • 3
  • 22
  • 35