title: Moving not empty directory recursively using Java NIO.2 FileVisitor and Files.walkFileTree(...)
body: <p>I saw a lot of examples of how to copy or delete files recursively by using  Java NIO.2. For example, this is how to copy a folder with all its contents:</p>
  
  <pre><code>/**
   * Copies a folder with all contents recursively. Class implements
   * {@code FileVisitor} interface.
   * @author Ernestas Gruodis
   */
  public static class TreeCopy implements FileVisitor&lt;Path&gt; {
  
          private final Path source;
          private final Path target;
          private final boolean replace;
          private final CopyOption[] options;
          private final ArrayList&lt;Object[]&gt; events = new ArrayList&lt;&gt;();
  
          /**
           * Copies a folder with all contents recursively.
           *
           * @param source source file path.
           * @param target target file path.
           * @param replace {@code true} if existing file should be replaced.
           */
          public TreeCopy(Path source, Path target, boolean replace) {
              this.source = source;
              this.target = target;
              this.replace = replace;
  
              options = replace ? new CopyOption[]{COPY_ATTRIBUTES, REPLACE_EXISTING} : new CopyOption[0];
          }
  
          @Override
          public synchronized FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
  
              Path newDir = target.resolve(source.relativize(dir));
              try {
                  Files.copy(dir, newDir, options);
              } catch (FileAlreadyExistsException ex) {
                  if (!replace) {
                      events.add(new Object[]{"Folder already exists", newDir, ex});
                      return FileVisitResult.TERMINATE;
                  } else {
                      return FileVisitResult.CONTINUE;
                  }
              } catch (DirectoryNotEmptyException ex) {
                  //Ignore
              } catch (IOException ex) {
                  events.add(new Object[]{"Unable to create a folder", newDir, ex});
                  return FileVisitResult.SKIP_SUBTREE;
              }
              return FileVisitResult.CONTINUE;
          }
  
          @Override
          public synchronized FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
  
              Path newFile = target.resolve(source.relativize(file));
              try {
                  Files.copy(file, newFile, options);
              } catch (FileAlreadyExistsException ex) {
                  events.add(new Object[]{"File already exists", newFile, ex});
              } catch (NoSuchFileException ex) {
                  events.add(new Object[]{"No such file", newFile.getParent(), ex});
              } catch (IOException ex) {
                  events.add(new Object[]{"Unable to create a file", newFile, ex});
              }
              return FileVisitResult.CONTINUE;
          }
  
          @Override
          public synchronized FileVisitResult postVisitDirectory(Path dir, IOException exc) {
  
              if (exc == null) {
                  Path newDir = target.resolve(source.relativize(dir));
                  try {
                      FileTime time = Files.getLastModifiedTime(dir);
                      Files.setLastModifiedTime(newDir, time);
                  } catch (IOException ex) {
                      events.add(new Object[]{"Unable to copy all attributes to", newDir, ex});
                  }
              }
              return FileVisitResult.CONTINUE;
          }
  
          @Override
          public synchronized FileVisitResult visitFileFailed(Path file, IOException ex) {
  
              if (ex instanceof FileSystemLoopException) {
                  events.add(new Object[]{"Cycle detected", file, ex});
              } else {
                  events.add(new Object[]{"Unable to copy", file, ex});
              }
              return FileVisitResult.CONTINUE;
          }
  
          /**
           * Returns errors which happened while copying a directory.
           *
           * @return {@code ArrayList&lt;Object[]&gt;} error list, where at each entry
           * of {@code Object[]} index:
           * &lt;ul&gt;&lt;li&gt; 0 - {@code String} - error description;
           * &lt;/li&gt;&lt;li&gt; 1 - {@code Path} - target folder/file path;
           * &lt;/li&gt;&lt;li&gt; 2 - {@code Exception} - specific exception.
           * &lt;/li&gt;&lt;/ul&gt;
           */
          public ArrayList&lt;Object[]&gt; getEvents() {
  
              return events;
          }
      }
  
  
  Path source = Paths.get("/toCopyDir"),
      target = Paths.get("/someDir2/etc/toCopyDir");
  
  EnumSet&lt;FileVisitOption&gt; opts = EnumSet.of(FileVisitOption.FOLLOW_LINKS);
  TreeCopy tc = new TreeCopy(source, target, true);
  try {
     Files.walkFileTree(source, opts, Integer.MAX_VALUE, tc);
  } catch (IOException ex) {
     //Handle exception
  }
  </code></pre>
  
  <p>But how to move the folder containing files? There is a method <code>Files.move(Path source, Path target, CopyOption... options) throws IOException</code>. Can anyone give a real effective example?</p>
  
  <p>I think the solution could be to use <code>Files.copy(...)</code> in <code>preVisitDirectory(...)</code>, and then <code>Files.delete(...)</code> in <code>postVisitDirectory(...)</code>, something like that..</p>