yakworks.commons.io.PathTools.groovy Maven / Gradle / Ivy
/*
* Copyright 2021 original authors
* SPDX-License-Identifier: Apache-2.0
*/
package yakworks.commons.io
import java.nio.file.FileVisitResult
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.nio.file.SimpleFileVisitor
import java.nio.file.StandardCopyOption
import java.nio.file.attribute.BasicFileAttributes
import groovy.transform.CompileStatic
import org.apache.commons.io.file.Counters
import org.apache.commons.io.file.PathUtils
import yakworks.commons.lang.Validate
import static java.nio.file.FileVisitOption.FOLLOW_LINKS
/**
* Utility methods for copying or deleting from the file system.
*/
@CompileStatic
abstract class PathTools {
/**
* Deletes a directory recursively. does not throw error, returns false on IOException
*/
static boolean deleteDirectory(Path root) {
if (root == null) {
return false
}
try {
return PathUtils.deleteDirectory(root)
}
catch (IOException ex) {
return false
}
}
/**
* Deletes a directory recursively. does not throw error, returns false on IOException
* Deletes a file or directory recursively. If the path is a directory, delete it and all sub-directories.
*
* The difference between File.delete() and this method are:
* - A directory to delete does not have to be empty.
* - You get exceptions when a file or directory cannot be deleted; File.delete() returns a boolean.
*
* @return the count of files and dirs deleted or 0
* @throws IOException if an I/O error occurs
*/
static long delete(Path fileOrDir) {
if (fileOrDir == null) return 0
Counters.PathCounters cntr = PathUtils.delete(fileOrDir)
return cntr.directoryCounter.get() + cntr.fileCounter.get()
}
/**
* Recursively copy the contents of the {@code src} file/directory
* to the {@code dest} file/directory.
*/
static void copyRecursively(Path src, Path dest) {
Validate.notNull(src, '[src]')
Validate.notNull(src, '[dest]')
BasicFileAttributes srcAttr = Files.readAttributes(src, BasicFileAttributes)
if (srcAttr.isDirectory()) {
Files.walkFileTree(src, EnumSet.of(FOLLOW_LINKS), Integer.MAX_VALUE, new SimpleFileVisitor() {
@Override
FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
Files.createDirectories(dest.resolve(src.relativize(dir)))
return FileVisitResult.CONTINUE
}
@Override
FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
Files.copy(file, dest.resolve(src.relativize(file)), StandardCopyOption.REPLACE_EXISTING)
return FileVisitResult.CONTINUE
}
})
}
else if (srcAttr.isRegularFile()) {
Files.copy(src, dest)
}
else {
throw new IllegalArgumentException("Source File must denote a directory or file")
}
}
/**
* Files.createDirectories to ensure its created, checks if exists first.
*/
static Path createDirectories(Path dir){
if(!Files.exists(dir)) return Files.createDirectories(dir)
return dir
}
/**
* Creates the parent directories for the given path.
* the Path.getParent might not operate as one would expect. check out its javadocs to understand what this does
* @see Path#getParent
* @see Files#createDirectories
*/
static Path createParentDirectories(Path path){
final Path parent = path.getParent()
if (parent == null) {
return null
}
return Files.createDirectories(parent);
}
static String getBaseName(String filename) {
return getBaseName(Paths.get(filename))
}
/**
* get base filename without extension for path
* 'foo'->'foo', 'foo.txt'->'foo', 'foo.tar.gz'->'foo.tar'
* @return the base name. will be same if no ext exists.
* @see #getBaseName
*/
static String getBaseName(Path path) {
return removeFileExtension(path.fileName.toString())
}
/**
* Strips the
* @param filename the filename to remove ext
* @param removeAllExtensions if true then foo.tar.gz will return foo
* @return the name without extenstion
*/
static String removeFileExtension(String filename, boolean removeAllExtensions = false) {
if (filename == null || filename.isEmpty()) return filename
return filename.replaceAll(extensionPattern(removeAllExtensions), "")
}
/**
* regex pattern to get extension from filename string ,
* if wholeExtension is true then will match the .tar.gz in foo.tar.gz instead of just the .gz
*/
static String extensionPattern(boolean wholeExtension = false) {
return '(?