41 import java.nio.file.*;
42 import static java.nio.file.StandardCopyOption.*;
43 import java.nio.file.attribute.*;
44 import static java.nio.file.FileVisitResult.*;
45 import java.io.IOException;
57 static boolean okayToOverwrite(Path file) {
58 String answer = System.console().readLine(
"overwrite %s (yes/no)? ", file);
59 return (answer.equalsIgnoreCase(
"y") || answer.equalsIgnoreCase(
"yes"));
67 static void copyFile(Path source, Path target,
boolean prompt,
boolean preserve) {
68 CopyOption[] options = (preserve) ?
69 new CopyOption[] { COPY_ATTRIBUTES, REPLACE_EXISTING } :
70 new CopyOption[] { REPLACE_EXISTING };
71 if (!prompt || Files.notExists(target) || okayToOverwrite(target)) {
73 Files.copy(source, target, options);
74 }
catch (IOException x) {
75 System.err.format(
"Unable to copy: %s: %s%n", source, x);
83 static class TreeCopier
implements FileVisitor<Path> {
84 private final Path source;
85 private final Path target;
86 private final boolean prompt;
87 private final boolean preserve;
89 TreeCopier(Path source, Path target,
boolean prompt,
boolean preserve) {
93 this.preserve = preserve;
97 public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
100 CopyOption[] options = (preserve) ?
101 new CopyOption[] { COPY_ATTRIBUTES } :
new CopyOption[0];
103 Path newdir = target.resolve(source.relativize(dir));
105 Files.copy(dir, newdir, options);
106 }
catch (FileAlreadyExistsException x) {
108 }
catch (IOException x) {
109 System.err.format(
"Unable to create: %s: %s%n", newdir, x);
116 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
117 copyFile(file, target.resolve(source.relativize(file)),
123 public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
125 if (exc ==
null && preserve) {
126 Path newdir = target.resolve(source.relativize(dir));
128 FileTime time = Files.getLastModifiedTime(dir);
129 Files.setLastModifiedTime(newdir, time);
130 }
catch (IOException x) {
131 System.err.format(
"Unable to copy all attributes to: %s: %s%n", newdir, x);
138 public FileVisitResult visitFileFailed(Path file, IOException exc) {
139 if (exc instanceof FileSystemLoopException) {
140 System.err.println(
"cycle detected: " + file);
142 System.err.format(
"Unable to copy: %s: %s%n", file, exc);
148 static void usage() {
149 System.err.println(
"java Copy [-ip] source... target");
150 System.err.println(
"java Copy -r [-ip] source-dir... target");
154 public static void main(String[] args)
throws IOException {
155 boolean recursive =
false;
156 boolean prompt =
false;
157 boolean preserve =
false;
161 while (argi < args.length) {
162 String arg = args[argi];
163 if (!arg.startsWith(
"-"))
165 if (arg.length() < 2)
167 for (
int i=1; i<arg.length(); i++) {
168 char c = arg.charAt(i);
170 case 'r' : recursive =
true;
break;
171 case 'i' : prompt =
true;
break;
172 case 'p' : preserve =
true;
break;
180 int remaining = args.length - argi;
183 Path[] source =
new Path[remaining-1];
185 while (remaining > 1) {
186 source[i++] = Paths.get(args[argi++]);
189 Path target = Paths.get(args[argi]);
192 boolean isDir = Files.isDirectory(target);
195 for (i=0; i<source.length; i++) {
196 Path dest = (isDir) ? target.resolve(source[i].getFileName()) : target;
200 EnumSet<FileVisitOption> opts = EnumSet.of(FileVisitOption.FOLLOW_LINKS);
201 TreeCopier tc =
new TreeCopier(source[i], dest, prompt, preserve);
202 Files.walkFileTree(source[i], opts, Integer.MAX_VALUE, tc);
205 if (Files.isDirectory(source[i])) {
206 System.err.format(
"%s: is a directory%n", source[i]);
209 copyFile(source[i], dest, prompt, preserve);