public static boolean delete(@NotNull File file) {
    FileAttributes attributes = FileSystemUtil.getAttributes(file);
    if (attributes == null) return true;

    if (attributes.isDirectory() && !attributes.isSymLink()) {
      File[] files = file.listFiles();
      if (files != null) {
        for (File child : files) {
          if (!delete(child)) return false;
        }
      }
    }

    return deleteFile(file);
  }
  private static void performCopy(
      @NotNull File fromFile, @NotNull File toFile, final boolean syncTimestamp)
      throws IOException {
    final FileOutputStream fos;
    try {
      fos = openOutputStream(toFile);
    } catch (IOException e) {
      if (SystemInfo.isWindows
          && e.getMessage() != null
          && e.getMessage().contains("denied")
          && WinUACTemporaryFix.nativeCopy(fromFile, toFile, syncTimestamp)) {
        return;
      }
      throw e;
    }

    try {
      final FileInputStream fis = new FileInputStream(fromFile);
      try {
        copy(fis, fos);
      } finally {
        fis.close();
      }
    } finally {
      fos.close();
    }

    if (syncTimestamp) {
      final long timeStamp = fromFile.lastModified();
      if (timeStamp < 0) {
        LOG.warn("Invalid timestamp " + timeStamp + " of '" + fromFile + "'");
      } else if (!toFile.setLastModified(timeStamp)) {
        LOG.warn("Unable to set timestamp " + timeStamp + " to '" + toFile + "'");
      }
    }

    if (SystemInfo.isUnix && fromFile.canExecute()) {
      FileSystemUtil.clonePermissions(fromFile.getPath(), toFile.getPath());
    }
  }