com.esotericsoftware.wildcard.Paths Maven / Gradle / Ivy
package com.esotericsoftware.wildcard;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* Collects filesystem paths using wildcards, preserving the directory structure. Copies, deletes, and zips paths.
*
*
* Code Source
*
*
*
* This is external code that was copied into the CedarCommon codebase under
* the terms of its license.
*
*
*
*
*
*
* Source:
* Wildcard
*
*
* Date:
* April, 2014
*
*
*
*
*/
public class Paths implements Iterable {
static private final Comparator LONGEST_TO_SHORTEST = new Comparator() {
public int compare (Path s1, Path s2) {
return s2.absolute().length() - s1.absolute().length();
}
};
static private List defaultGlobExcludes;
final List paths = new ArrayList(32);
/**
* Creates an empty Paths object.
*/
public Paths () {
}
/**
* Creates a Paths object and calls {@link #glob(String, String[])} with the specified arguments.
*/
public Paths (String dir, String... patterns) {
glob(dir, patterns);
}
/**
* Creates a Paths object and calls {@link #glob(String, List)} with the specified arguments.
*/
public Paths (String dir, List patterns) {
glob(dir, patterns);
}
/**
* Collects all files and directories in the specified directory matching the wildcard patterns.
* @param dir The directory containing the paths to collect. If it does not exist, no paths are collected. If null, "." is
* assumed.
* @param patterns The wildcard patterns of the paths to collect or exclude. Patterns may optionally contain wildcards
* represented by asterisks and question marks. If empty or omitted then the dir parameter is split on the "|"
* character, the first element is used as the directory and remaining are used as the patterns. If null, ** is
* assumed (collects all paths).
*
* A single question mark (?) matches any single character. Eg, something? collects any path that is named
* "something" plus any character.
*
* A single asterisk (*) matches any characters up to the next slash (/). Eg, *\*\something* collects any path that
* has two directories of any name, then a file or directory that starts with the name "something".
*
* A double asterisk (**) matches any characters. Eg, **\something\** collects any path that contains a directory
* named "something".
*
* A pattern starting with an exclamation point (!) causes paths matched by the pattern to be excluded, even if other
* patterns would select the paths.
*/
public void glob (String dir, String... patterns) {
if (dir == null) dir = ".";
if (patterns != null && patterns.length == 0) {
String[] split = dir.split("\\|");
if (split.length > 1) {
dir = split[0];
patterns = new String[split.length - 1];
for (int i = 1, n = split.length; i < n; i++)
patterns[i - 1] = split[i];
}
}
File dirFile = new File(dir);
if (!dirFile.exists()) return;
List includes = new ArrayList();
List excludes = new ArrayList();
if (patterns != null) {
for (String pattern : patterns) {
if (pattern.charAt(0) == '!')
excludes.add(pattern.substring(1));
else
includes.add(pattern);
}
}
if (includes.isEmpty()) includes.add("**");
if (defaultGlobExcludes != null) excludes.addAll(defaultGlobExcludes);
GlobScanner scanner = new GlobScanner(dirFile, includes, excludes);
String rootDir = scanner.rootDir().getPath().replace('\\', '/');
if (!rootDir.endsWith("/")) rootDir += '/';
for (String filePath : scanner.matches())
paths.add(new Path(rootDir, filePath));
}
/**
* Calls {@link #glob(String, String...)}.
*/
public void glob (String dir, List patterns) {
if (patterns == null) throw new IllegalArgumentException("patterns cannot be null.");
glob(dir, patterns.toArray(new String[patterns.size()]));
}
/**
* Collects all files and directories in the specified directory matching the regular expression patterns. This method is much
* slower than {@link #glob(String, String...)} because every file and directory under the specified directory must be
* inspected.
* @param dir The directory containing the paths to collect. If it does not exist, no paths are collected.
* @param patterns The regular expression patterns of the paths to collect or exclude. If empty or omitted then the dir
* parameter is split on the "|" character, the first element is used as the directory and remaining are used as the
* patterns. If null, ** is assumed (collects all paths).
*
* A pattern starting with an exclamation point (!) causes paths matched by the pattern to be excluded, even if other
* patterns would select the paths.
*/
public void regex (String dir, String... patterns) {
if (dir == null) dir = ".";
if (patterns != null && patterns.length == 0) {
String[] split = dir.split("\\|");
if (split.length > 1) {
dir = split[0];
patterns = new String[split.length - 1];
for (int i = 1, n = split.length; i < n; i++)
patterns[i - 1] = split[i];
}
}
File dirFile = new File(dir);
if (!dirFile.exists()) return;
List includes = new ArrayList();
List excludes = new ArrayList();
if (patterns != null) {
for (String pattern : patterns) {
if (pattern.charAt(0) == '!')
excludes.add(pattern.substring(1));
else
includes.add(pattern);
}
}
if (includes.isEmpty()) includes.add(".*");
RegexScanner scanner = new RegexScanner(dirFile, includes, excludes);
String rootDir = scanner.rootDir().getPath().replace('\\', '/');
if (!rootDir.endsWith("/")) rootDir += '/';
for (String filePath : scanner.matches())
paths.add(new Path(rootDir, filePath));
}
/**
* Copies the files and directories to the specified directory.
* @return A paths object containing the paths of the new files.
*/
public Paths copyTo (String destDir) throws IOException {
Paths newPaths = new Paths();
for (Path path : paths) {
File destFile = new File(destDir, path.name);
File srcFile = path.file();
if (srcFile.isDirectory()) {
destFile.mkdirs();
} else {
destFile.getParentFile().mkdirs();
copyFile(srcFile, destFile);
}
newPaths.paths.add(new Path(destDir, path.name));
}
return newPaths;
}
/**
* Deletes all the files, directories, and any files in the directories.
* @return False if any file could not be deleted.
*/
public boolean delete () {
boolean success = true;
List pathsCopy = new ArrayList(paths);
Collections.sort(pathsCopy, LONGEST_TO_SHORTEST);
for (File file : getFiles(pathsCopy)) {
if (file.isDirectory()) {
if (!deleteDirectory(file)) success = false;
} else {
if (!file.delete()) success = false;
}
}
return success;
}
/**
* Compresses the files and directories specified by the paths into a new zip file at the specified location. If there are no
* paths or all the paths are directories, no zip file will be created.
*/
public void zip (String destFile) throws IOException {
Paths zipPaths = filesOnly();
if (zipPaths.paths.isEmpty()) return;
byte[] buf = new byte[1024];
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(destFile));
try {
for (Path path : zipPaths.paths) {
File file = path.file();
out.putNextEntry(new ZipEntry(path.name.replace('\\', '/')));
FileInputStream in = new FileInputStream(file);
int len;
while ((len = in.read(buf)) > 0)
out.write(buf, 0, len);
in.close();
out.closeEntry();
}
} finally {
out.close();
}
}
public int count () {
return paths.size();
}
public boolean isEmpty () {
return paths.isEmpty();
}
/**
* Returns the absolute paths delimited by the specified character.
*/
public String toString (String delimiter) {
StringBuffer buffer = new StringBuffer(256);
for (String path : getPaths()) {
if (buffer.length() > 0) buffer.append(delimiter);
buffer.append(path);
}
return buffer.toString();
}
/**
* Returns the absolute paths delimited by commas.
*/
public String toString () {
return toString(", ");
}
/**
* Returns a Paths object containing the paths that are files.
*/
public Paths filesOnly () {
Paths newPaths = new Paths();
for (Path path : paths) {
if (path.file().isFile()) newPaths.paths.add(path);
}
return newPaths;
}
/**
* Returns a Paths object containing the paths that are directories.
*/
public Paths dirsOnly () {
Paths newPaths = new Paths();
for (Path path : paths) {
if (path.file().isDirectory()) newPaths.paths.add(path);
}
return newPaths;
}
/**
* Returns the paths as File objects.
*/
public List getFiles () {
return getFiles(paths);
}
private ArrayList getFiles (List paths) {
ArrayList files = new ArrayList(paths.size());
int i = 0;
for (Path path : paths)
files.add(path.file());
return files;
}
/**
* Returns the portion of the path after the root directory where the path was collected.
*/
public List getRelativePaths () {
ArrayList stringPaths = new ArrayList(paths.size());
int i = 0;
for (Path path : paths)
stringPaths.add(path.name);
return stringPaths;
}
/**
* Returns the full paths.
*/
public List getPaths () {
ArrayList stringPaths = new ArrayList(paths.size());
int i = 0;
for (File file : getFiles())
stringPaths.add(file.getPath());
return stringPaths;
}
/**
* Returns the paths' filenames.
*/
public List getNames () {
ArrayList stringPaths = new ArrayList(paths.size());
int i = 0;
for (File file : getFiles())
stringPaths.add(file.getName());
return stringPaths;
}
/**
* Adds a single path to this Paths object.
*/
public void add (String dir, String name) {
paths.add(new Path(dir, name));
}
/**
* Adds all paths from the specified Paths object to this Paths object.
*/
public void add (Paths paths) {
this.paths.addAll(paths.paths);
}
/**
* Iterates over the absolute paths. The iterator supports the remove method.
*/
public Iterator iterator () {
return new Iterator() {
private Iterator iter = paths.iterator();
public void remove () {
iter.remove();
}
public String next () {
return iter.next().absolute();
}
public boolean hasNext () {
return iter.hasNext();
}
};
}
/**
* Iterates over the paths as File objects. The iterator supports the remove method.
*/
public Iterator fileIterator () {
return new Iterator() {
private Iterator iter = paths.iterator();
public void remove () {
iter.remove();
}
public File next () {
return iter.next().file();
}
public boolean hasNext () {
return iter.hasNext();
}
};
}
static private final class Path {
public final String dir;
public final String name;
public Path (String dir, String name) {
this.dir = dir;
this.name = name;
}
public String absolute () {
return dir + name;
}
public File file () {
return new File(dir, name);
}
}
/**
* Sets the exclude patterns that will be used in addition to the excludes specified for all glob searches.
*/
static public void setDefaultGlobExcludes (String... defaultGlobExcludes) {
Paths.defaultGlobExcludes = Arrays.asList(defaultGlobExcludes);
}
/**
* Copies one file to another.
*/
static private void copyFile (File in, File out) throws IOException {
FileChannel sourceChannel = new FileInputStream(in).getChannel();
FileChannel destinationChannel = new FileOutputStream(out).getChannel();
sourceChannel.transferTo(0, sourceChannel.size(), destinationChannel);
sourceChannel.close();
destinationChannel.close();
}
/**
* Deletes a directory and all files and directories it contains.
*/
static private boolean deleteDirectory (File file) {
if (file.exists()) {
File[] files = file.listFiles();
for (int i = 0, n = files.length; i < n; i++) {
if (files[i].isDirectory())
deleteDirectory(files[i]);
else
files[i].delete();
}
}
return file.delete();
}
public static void main (String[] args) {
if (args.length == 0) {
System.out.println("Usage: dir [pattern] [, pattern ...]");
System.exit(0);
}
List patterns = Arrays.asList(args);
patterns = patterns.subList(1, patterns.size());
for (String path : new Paths(args[0], patterns))
System.out.println(path);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy