* support recreating folder structure with hardlink files (e.g. when using --action hardlink to process disk folders)

This commit is contained in:
Reinhard Pointner 2014-07-15 12:57:07 +00:00
parent 731ef2de81
commit 939f623e71
2 changed files with 40 additions and 10 deletions

View File

@ -2,6 +2,7 @@ package net.filebot;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files;
import net.filebot.util.FileUtilities; import net.filebot.util.FileUtilities;
@ -31,7 +32,7 @@ public enum StandardRenameAction implements RenameAction {
// move file and the create a symlink to the new location via NIO.2 // move file and the create a symlink to the new location via NIO.2
try { try {
java.nio.file.Files.move(from.toPath(), destionation.toPath()); Files.move(from.toPath(), destionation.toPath());
FileUtilities.createRelativeSymlink(from, destionation, true); FileUtilities.createRelativeSymlink(from, destionation, true);
} catch (LinkageError e) { } catch (LinkageError e) {
throw new Exception("Unsupported Operation: move, createSymbolicLink"); throw new Exception("Unsupported Operation: move, createSymbolicLink");
@ -64,12 +65,10 @@ public enum StandardRenameAction implements RenameAction {
// create hardlink via NIO.2 // create hardlink via NIO.2
try { try {
java.nio.file.Files.createLink(destionation.toPath(), from.toPath()); return FileUtilities.createHardLinkStructure(destionation, from);
} catch (LinkageError e) { } catch (LinkageError e) {
throw new Exception("Unsupported Operation: createLink"); throw new Exception("Unsupported Operation: createLink");
} }
return destionation;
} }
}, },

View File

@ -17,11 +17,17 @@ import java.nio.ByteBuffer;
import java.nio.channels.FileChannel; import java.nio.channels.FileChannel;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.file.AtomicMoveNotSupportedException; import java.nio.file.AtomicMoveNotSupportedException;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator; import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
@ -58,9 +64,9 @@ public final class FileUtilities {
} else { } else {
// on Windows ATOMIC_MOVE allows us to rename files even if only lower/upper-case changes (without ATOMIC_MOVE the operation would be ignored) // on Windows ATOMIC_MOVE allows us to rename files even if only lower/upper-case changes (without ATOMIC_MOVE the operation would be ignored)
try { try {
java.nio.file.Files.move(source.toPath(), destination.toPath(), StandardCopyOption.ATOMIC_MOVE); Files.move(source.toPath(), destination.toPath(), StandardCopyOption.ATOMIC_MOVE);
} catch (AtomicMoveNotSupportedException e) { } catch (AtomicMoveNotSupportedException e) {
java.nio.file.Files.move(source.toPath(), destination.toPath(), StandardCopyOption.REPLACE_EXISTING); Files.move(source.toPath(), destination.toPath(), StandardCopyOption.REPLACE_EXISTING);
} }
} }
@ -76,7 +82,7 @@ public final class FileUtilities {
org.apache.commons.io.FileUtils.copyDirectory(source, destination); org.apache.commons.io.FileUtils.copyDirectory(source, destination);
} else { } else {
// copy file // copy file
java.nio.file.Files.copy(source.toPath(), destination.toPath(), StandardCopyOption.REPLACE_EXISTING); Files.copy(source.toPath(), destination.toPath(), StandardCopyOption.REPLACE_EXISTING);
} }
return destination; return destination;
@ -114,7 +120,30 @@ public final class FileUtilities {
} }
// create symlink via NIO.2 // create symlink via NIO.2
return java.nio.file.Files.createSymbolicLink(link.toPath(), target.toPath()).toFile(); return Files.createSymbolicLink(link.toPath(), target.toPath()).toFile();
}
public static File createHardLinkStructure(File link, File target) throws IOException {
if (target.isFile()) {
return Files.createLink(link.toPath(), target.toPath()).toFile();
}
// if the target is a directory, recreate the structure and hardlink each file item
final Path source = target.getCanonicalFile().toPath();
final Path destination = link.getCanonicalFile().toPath();
Files.walkFileTree(source, EnumSet.of(FileVisitOption.FOLLOW_LINKS), FILE_WALK_MAX_DEPTH, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Path linkFile = destination.resolve(source.relativize(file));
Files.createDirectories(linkFile.getParent());
Files.createLink(linkFile, file);
return FileVisitResult.CONTINUE;
}
});
return destination.toFile();
} }
public static boolean delete(File file) { public static boolean delete(File file) {
@ -391,16 +420,18 @@ public final class FileUtilities {
return asList(files); return asList(files);
} }
public static final int FILE_WALK_MAX_DEPTH = 32;
public static List<File> listFiles(File... folders) { public static List<File> listFiles(File... folders) {
return listFiles(asList(folders)); return listFiles(asList(folders));
} }
public static List<File> listFiles(Iterable<File> folders) { public static List<File> listFiles(Iterable<File> folders) {
return listFiles(folders, 32, false, true, false); return listFiles(folders, FILE_WALK_MAX_DEPTH, false, true, false);
} }
public static List<File> listFolders(Iterable<File> folders) { public static List<File> listFolders(Iterable<File> folders) {
return listFiles(folders, 32, false, false, true); return listFiles(folders, FILE_WALK_MAX_DEPTH, false, false, true);
} }
public static List<File> listFiles(Iterable<File> folders, int maxDepth, boolean addHidden, boolean addFiles, boolean addFolders) { public static List<File> listFiles(Iterable<File> folders, int maxDepth, boolean addHidden, boolean addFiles, boolean addFolders) {