title: java.nio.file.Files.delete(Path path) - occasional failure to recursively delete directory using SimpleFileVisitor
body: <p>Trying to troubleshoot an occasional <code>java.nio.file.DirectoryNotEmptyException</code> in a recursive delete method taken from <a href="https://stackoverflow.com/questions/779519/delete-files-recursively-in-java/8685959#8685959">Delete directories recursively in Java</a></p>
  <p><strong>Code</strong> (credit to @TrevorRobinson) :</p>
  <pre><code>static void removeRecursive(Path path) throws IOException {
      Files.walkFileTree(path, new SimpleFileVisitor&lt;Path&gt;() {
  
          final Logger logger = LoggerFactory.getLogger(this.getClass());
          @Override
          public FileVisitResult visitFile(Path file,
                  BasicFileAttributes attrs) throws IOException {
              logger.warn(&quot;Deleting &quot; + file.getFileName());
              Files.delete(file);
              logger.warn(&quot;DELETED &quot; + file.getFileName());
              return FileVisitResult.CONTINUE;
          }
  
          @Override
          public FileVisitResult visitFileFailed(Path file, IOException exc) {
              // try to delete the file anyway, even if its attributes could
              // not be read, since delete-only access is theoretically possible
              // I NEVER SEE THIS
              logger.warn(&quot;Delete file &quot; + file + &quot; failed&quot;, exc);
              try {
                  Files.delete(file);
              } catch (IOException e) {
                  logger.warn(
                      &quot;Delete file &quot; + file + &quot; failed again&quot;, exc);
              }
              return FileVisitResult.CONTINUE;
          }
  
          @Override
          public FileVisitResult postVisitDirectory(Path dir, IOException exc)
                  throws IOException {
              if (exc == null) {
                  Files.delete(dir);
                  return FileVisitResult.CONTINUE;
              }
              // directory iteration failed; propagate exception
              throw exc;
          }
      });
  }
  </code></pre>
  <p><strong>Call</strong>:</p>
  <pre><code>try {
      removeRecursive(Paths.get(unzipDirPath));
  } catch (IOException e) {
      String msg = &quot;Failed to delete folder &quot; + unzipDirPath;
      if (e instanceof java.nio.file.DirectoryNotEmptyException) {
          msg += &quot;. Still contains : &quot;;
          final File[] listFiles = Paths.get(unzipDirPath).toFile().listFiles();
          if (listFiles != null) for (File file : listFiles) {
              msg += file.getAbsolutePath() + &quot;\n&quot;;
          }
      }
      log.error(msg, e);
  }
  </code></pre>
  <p><strong>Prints</strong> (once in 20/40 iterations):</p>
  <pre class="lang-none prettyprint-override"><code>22:03:34.190 [http-bio-8080-exec-47] WARN  g.u.d.m.server.servlets.Controller$1 - Deleting batt
  22:03:34.192 [http-bio-8080-exec-47] WARN  g.u.d.m.server.servlets.Controller$1 - DELETED batt
  22:03:34.192 [http-bio-8080-exec-47] WARN  g.u.d.m.server.servlets.Controller$1 - Deleting wifi
  22:03:34.193 [http-bio-8080-exec-47] WARN  g.u.d.m.server.servlets.Controller$1 - DELETED wifi
  22:03:34.196 [http-bio-8080-exec-47] ERROR g.u.d.m.s.s.DataCollectionServlet - Failed to delete folder C:\yada\. Still contains : C:\yada\dir\wifi
  
  java.nio.file.DirectoryNotEmptyException: C:\yada\dir
      at sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:265) ~[na:1.7.0_45]
      at sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:103) ~[na:1.7.0_45]
      at java.nio.file.Files.delete(Files.java:1077) ~[na:1.7.0_45]
      at gr.uoa.di.monitoring.server.servlets.Controller$1.postVisitDirectory(Controller.java:128) ~[Controller$1.class:na]
      at gr.uoa.di.monitoring.server.servlets.Controller$1.postVisitDirectory(Controller.java:1) ~[Controller$1.class:na]
      at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:224) ~[na:1.7.0_45]
      at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:199) ~[na:1.7.0_45]
      at java.nio.file.FileTreeWalker.walk(FileTreeWalker.java:69) ~[na:1.7.0_45]
      at java.nio.file.Files.walkFileTree(Files.java:2600) ~[na:1.7.0_45]
      at java.nio.file.Files.walkFileTree(Files.java:2633) ~[na:1.7.0_45]
      at gr.uoa.di.monitoring.server.servlets.Controller.removeRecursive(Controller.java:96) ~[Controller.class:na]
      at gr.uoa.di.monitoring.server.servlets.DataCollectionServlet.doPost(DataCollectionServlet.java:153) ~[DataCollectionServlet.class:na]
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:641) [servlet-api.jar:na]
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:722) [servlet-api.jar:na]
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) [catalina.jar:7.0.32]
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) [catalina.jar:7.0.32]
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) [catalina.jar:7.0.32]
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) [catalina.jar:7.0.32]
      at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) [catalina.jar:7.0.32]
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168) [catalina.jar:7.0.32]
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) [catalina.jar:7.0.32]
      at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929) [catalina.jar:7.0.32]
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) [catalina.jar:7.0.32]
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) [catalina.jar:7.0.32]
      at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002) [tomcat-coyote.jar:7.0.32]
      at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585) [tomcat-coyote.jar:7.0.32]
      at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310) [tomcat-coyote.jar:7.0.32]
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_45]
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_45]
      at java.lang.Thread.run(Thread.java:744) [na:1.7.0_45]
  </code></pre>
  <p>Notice that <code>wifi</code> is reported as deleted - what's even more weird is that sometimes I get :</p>
  <blockquote>
  <p>Failed to delete folder C:\yada. Still contains : C:\yada\dir</p>
  <p>java.nio.file.DirectoryNotEmptyException: C:\yada\dir</p>
  </blockquote>
  <p>I tend towards the conclusion that occasionally the deletion takes too long - in other words the problem is that <code>java.nio.file.Files.delete(Path path)</code> does not block (so C:\yada\dir still contains files when its time comes, which sometimes are deleted by the time I stat it). So how am I to workaround this ?</p>
  <p><strong>Also</strong> : is <code>java.nio.file.Files.delete(Path path)</code> required to throw ? The <a href="http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#delete%28java.nio.file.Path%29" rel="noreferrer">docs</a> state :</p>
  <blockquote>
  <p>On some operating systems it may not be possible to remove a file when it is open and in use by this Java virtual machine or other programs.</p>
  </blockquote>
  <p>Does not seem to require an exception to be thrown in this case. <em>Is <code>java.nio.file.Files.delete(Path path)</code> required to throw</em> ?</p>