FileIOUtils { public static int createDeepHardlink(final File sourceDir, final File destDir) throws IOException { if (!sourceDir.exists()) { throw new IOException("Source directory " + sourceDir.getPath() + " doesn't exist"); } else if (!destDir.exists()) { throw new IOException("Destination directory " + destDir.getPath() + " doesn't exist"); } else if (sourceDir.isFile() && destDir.isFile()) { throw new IOException("Source or Destination is not a directory."); } final Set<String> paths = new HashSet<>(); createDirsFindFiles(sourceDir, sourceDir, destDir, paths); int linkCount = 0; for (String path : paths) { final File sourceLink = new File(sourceDir, path); path = destDir + path; final File[] targetFiles = sourceLink.listFiles(); for (final File targetFile : targetFiles) { if (targetFile.isFile()) { final File linkFile = new File(path, targetFile.getName()); Files.createLink(linkFile.toPath(), Paths.get(targetFile.getAbsolutePath())); linkCount++; } } } return linkCount; }  static boolean isDirWritable(final File dir); static boolean isValidDirectory(File directory); static void deleteDirectorySilently(final File dir); static File getDirectory(File parentDirectory, String folderName); static void moveFiles(File sourceDirectory, File destinationDiretory, String fileNamePattern); static void dumpNumberToFile(final Path filePath, final long num); static long readNumberFromFile(final Path filePath); static String getSourcePathFromClass(final Class<?> containedClass); static String getCanonicalPath(final File f); static Props loadOutputFileProps(final File file); static File createOutputPropsFile(final String prefix,
      final String suffix, final String workingDir); static int createDeepHardlink(final File sourceDir, final File destDir); static Pair<Integer, Integer> readUtf8File(final File file, final int offset,
      final int length, final OutputStream stream); static LogData readUtf8File(final File file, final int fileOffset, final int length); static JobMetaData readUtf8MetaDataFile(final File file, final int fileOffset,
      final int length); static Pair<Integer, Integer> getUtf8Range(final byte[] buffer, final int offset,
      final int length);  }
@Test public void testHardlinkCopy() throws IOException { final int hardLinkCount = FileIOUtils.createDeepHardlink(this.sourceDir, this.destDir); assertThat(areDirsEqual(this.sourceDir, this.destDir, true)).isTrue(); FileUtils.deleteDirectory(this.destDir); assertThat(hardLinkCount).isEqualTo(5); assertThat(areDirsEqual(this.baseDir, this.sourceDir, true)).isTrue(); }
@Ignore("Slow test (over 30s) - run manually if need to touch createDeepHardlink()") @Test public void testHardlinkCopyOfBigDir() throws IOException { final File bigDir = new File(this.baseDir.getAbsolutePath() + "/bigdir"); bigDir.mkdir(); createBigDir(bigDir.getAbsolutePath()); FileIOUtils.createDeepHardlink(bigDir, this.destDir); assertThat(areDirsEqual(this.destDir, bigDir, true)).isTrue(); FileUtils.deleteDirectory(bigDir); }
@Test public void testHardlinkCopyNonSource() { assertThatThrownBy(() -> { FileIOUtils.createDeepHardlink(new File(this.sourceDir, "idonotexist"), this.destDir); }).isInstanceOf(IOException.class); }