4 import java.io.IOException;
5 import java.nio.file.FileSystems;
6 import java.nio.file.FileVisitOption;
7 import java.nio.file.FileVisitResult;
8 import java.nio.file.Files;
9 import java.nio.file.Path;
10 import java.nio.file.PathMatcher;
11 import java.nio.file.Paths;
12 import java.nio.file.SimpleFileVisitor;
13 import java.nio.file.attribute.BasicFileAttributes;
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.EnumSet;
17 import java.util.List;
18 import java.util.stream.Collectors;
20 public class FileUtils
23 * Given string glob pattern (see
24 * https://docs.oracle.com/javase/7/docs/api/java/nio/file/FileSystem.html#getPathMatcher(java.lang.String)
25 * ) return a List of Files that match the pattern.
26 * Note this is a java style glob, not necessarily a bash-style glob, though there are sufficient similarities.
28 public static List<File> getFilesFromGlob(String pattern)
30 return getFilesFromGlob(pattern, true);
33 public static List<File> getFilesFromGlob(String pattern,
34 boolean allowSingleFilenameThatDoesNotExist)
36 pattern = substituteHomeDir(pattern);
37 String relativePattern = pattern.startsWith(File.separator) ? null
39 List<File> files = new ArrayList<>();
41 * For efficiency of the Files.walkFileTree(), let's find the longest path that doesn't need globbing.
42 * We look for the first glob character * { ? and then look for the last File.separator before that.
43 * Then we can reset the path to look at and shorten the globbing pattern.
44 * Relative paths can be used in pattern, which work from the pwd (though these are converted into
45 * full paths in the match).
47 int firstGlobChar = -1;
48 boolean foundGlobChar = false;
49 for (char c : new char[] { '*', '{', '?' })
51 if (pattern.indexOf(c) > -1
52 && (pattern.indexOf(c) < firstGlobChar || !foundGlobChar))
54 firstGlobChar = pattern.indexOf(c);
58 int lastFS = pattern.lastIndexOf(File.separatorChar, firstGlobChar);
61 String pS = pattern.substring(0, lastFS + 1);
62 String rest = pattern.substring(lastFS + 1);
67 Path parentDir = Paths.get(pS);
68 if (parentDir.toFile().exists())
72 String glob = "glob:" + parentDir.toString() + File.separator
74 PathMatcher pm = FileSystems.getDefault().getPathMatcher(glob);
75 int maxDepth = rest.contains("**") ? 1028
77 .filter(ch -> ch == File.separatorChar).count())
80 Files.walkFileTree(parentDir,
81 EnumSet.of(FileVisitOption.FOLLOW_LINKS), maxDepth,
82 new SimpleFileVisitor<Path>()
85 public FileVisitResult visitFile(Path path,
86 BasicFileAttributes attrs) throws IOException
90 files.add(path.toFile());
92 return FileVisitResult.CONTINUE;
96 public FileVisitResult visitFileFailed(Path file,
97 IOException exc) throws IOException
99 return FileVisitResult.CONTINUE;
102 } catch (IOException e)
111 File f = new File(pattern);
112 if (allowSingleFilenameThatDoesNotExist || f.exists())
117 Collections.sort(files);
122 public static List<String> getFilenamesFromGlob(String pattern)
124 // convert list of Files to list of File.getPath() Strings
125 return getFilesFromGlob(pattern).stream().map(f -> f.getPath())
126 .collect(Collectors.toList());
129 public static String substituteHomeDir(String path)
131 return path.startsWith("~" + File.separator)
132 ? System.getProperty("user.home") + path.substring(1)
137 * This method returns the basename of File file
139 public static String getBasename(File file)
141 return getBasenameOrExtension(file, false);
145 * This method returns the extension of File file.
147 public static String getExtension(File file)
149 return getBasenameOrExtension(file, true);
152 public static String getBasenameOrExtension(File file, boolean extension)
158 String filename = file.getName();
159 int lastDot = filename.lastIndexOf('.');
160 if (lastDot > 0) // don't truncate if starts with '.'
162 value = extension ? filename.substring(lastDot + 1)
163 : filename.substring(0, lastDot);
167 value = extension ? "" : filename;
173 * This method returns the dirname of the first --append or --open value.
174 * Used primarily for substitutions in output filenames.
176 public static String getDirname(File file)
181 String dirname = null;
182 File p = file.getParentFile();
187 File d = new File(substituteHomeDir(p.getPath()));
188 dirname = d.getPath();
192 public static String convertWildcardsToPath(String value, String wildcard,
193 String dirname, String basename)
199 StringBuilder path = new StringBuilder();
200 int lastFileSeparatorIndex = value.lastIndexOf(File.separatorChar);
201 int wildcardBeforeIndex = value.indexOf(wildcard);
202 if (lastFileSeparatorIndex > wildcard.length() - 1
203 && wildcardBeforeIndex < lastFileSeparatorIndex)
205 path.append(value.substring(0, wildcardBeforeIndex));
206 path.append(dirname);
207 path.append(value.substring(wildcardBeforeIndex + wildcard.length(),
208 lastFileSeparatorIndex + 1));
212 path.append(value.substring(0, lastFileSeparatorIndex + 1));
214 int wildcardAfterIndex = value.indexOf(wildcard,
215 lastFileSeparatorIndex);
216 if (wildcardAfterIndex > lastFileSeparatorIndex)
218 path.append(value.substring(lastFileSeparatorIndex + 1,
219 wildcardAfterIndex));
220 path.append(basename);
221 path.append(value.substring(wildcardAfterIndex + wildcard.length()));
225 path.append(value.substring(lastFileSeparatorIndex + 1));
227 return path.toString();