Skip to content

Commit 1cfd132

Browse files
committed
cp, rm, and mv commands with flag support
- CpCommand supports flags: -r (recursive), -i (interactive), -v (verbose), and -b (backup). - RmCommand supports flags: -r (recursive), -f (force), and -i (interactive). - MvCommand supports flags: -i (interactive), -v (verbose), and -b (backup).
1 parent 69c4b38 commit 1cfd132

File tree

4 files changed

+331
-6
lines changed

4 files changed

+331
-6
lines changed
Lines changed: 119 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,122 @@
11
package com.unixtools.command.filemanagement;
22

3-
public class CpCommand {
4-
3+
import com.unixtools.core.Command;
4+
import java.io.*;
5+
import java.nio.file.*;
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
import java.util.Scanner;
9+
10+
public class CpCommand implements Command {
11+
private static final String VALID_FLAGS = "riv";
12+
private final Scanner scanner = new Scanner(System.in);
13+
14+
@Override
15+
public void execute(String[] args) {
16+
List<String> flags = new ArrayList<>();
17+
List<String> paths = new ArrayList<>();
18+
19+
parseArguments(args, flags, paths);
20+
if (!areFlagsValid(flags)) {
21+
System.out.println("Invalid usage. Valid flags are: " + VALID_FLAGS);
22+
return;
23+
}
24+
if (paths.size() != 2) {
25+
System.out.println("Invalid usage. Two paths required: source and destination.");
26+
return;
27+
}
28+
29+
String sourcePath = normalizePath(paths.get(0));
30+
String destinationPath = normalizePath(paths.get(1));
31+
boolean recursive = flags.contains("r");
32+
boolean interactive = flags.contains("i");
33+
boolean verbose = flags.contains("v");
34+
35+
try {
36+
copyPath(Paths.get(sourcePath), Paths.get(destinationPath), recursive, interactive, verbose);
37+
} catch (IOException e) {
38+
System.out.println("cp: error occurred - " + e.getMessage());
39+
}
40+
}
41+
42+
private void parseArguments(String[] args, List<String> flags, List<String> paths) {
43+
for (String arg : args) {
44+
if (arg.startsWith("-")) {
45+
for (char flag : arg.substring(1).toCharArray()) {
46+
flags.add(String.valueOf(flag));
47+
}
48+
} else {
49+
paths.add(arg);
50+
}
51+
}
52+
}
53+
54+
private boolean areFlagsValid(List<String> flags) {
55+
return flags.stream().allMatch(flag -> VALID_FLAGS.contains(flag.replace("-", "")));
56+
}
57+
58+
private void copyPath(Path source, Path destination, boolean recursive, boolean interactive, boolean verbose)
59+
throws IOException {
60+
if (!Files.exists(source)) {
61+
System.out.println("cp: '" + source + "' does not exist");
62+
return;
63+
}
64+
65+
if (Files.isDirectory(source) && Files.isRegularFile(destination)) {
66+
System.out.println("cp: cannot overwrite non-directory '" + destination + "' with directory '" + source + "'");
67+
return;
68+
}
69+
70+
if (Files.isDirectory(source)) {
71+
if (!recursive) {
72+
System.out.println("cp: omitting directory '" + source + "' without -r flag");
73+
return;
74+
}
75+
copyDirectory(source, destination, recursive, interactive, verbose);
76+
} else {
77+
Path target = Files.isDirectory(destination) ? destination.resolve(source.getFileName()) : destination;
78+
copyFile(source, target, interactive, verbose);
79+
}
80+
}
81+
82+
private void copyDirectory(Path sourceDir, Path destinationDir, boolean recursive, boolean interactive,
83+
boolean verbose) throws IOException {
84+
if (!Files.exists(destinationDir)) {
85+
Files.createDirectories(destinationDir);
86+
}
87+
try (DirectoryStream<Path> stream = Files.newDirectoryStream(sourceDir)) {
88+
for (Path path : stream) {
89+
Path destPath = destinationDir.resolve(sourceDir.relativize(path));
90+
if (Files.isDirectory(path)) {
91+
copyDirectory(path, destPath, recursive, interactive, verbose);
92+
} else {
93+
copyFile(path, destPath, interactive, verbose);
94+
}
95+
}
96+
}
97+
}
98+
99+
private void copyFile(Path sourceFile, Path destinationFile, boolean interactive, boolean verbose)
100+
throws IOException {
101+
if (Files.exists(destinationFile) && !confirmOverwrite(destinationFile)) {
102+
return;
103+
}
104+
105+
Files.copy(sourceFile, destinationFile, StandardCopyOption.REPLACE_EXISTING);
106+
if (verbose) {
107+
System.out.println("cp: copied '" + sourceFile + "' to '" + destinationFile + "'");
108+
}
109+
}
110+
111+
private boolean confirmOverwrite(Path file) {
112+
System.out.print("cp: overwrite '" + file + "'? (y/n) ");
113+
String response = scanner.nextLine();
114+
return response.equalsIgnoreCase("y");
115+
}
116+
117+
private String normalizePath(String path) {
118+
String normalizedPath = path.replace("\\", "/");
119+
Path pathObj = Paths.get(normalizedPath).normalize();
120+
return pathObj.toString();
121+
}
5122
}
Lines changed: 100 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,103 @@
11
package com.unixtools.command.filemanagement;
22

3-
public class MvCommand {
4-
3+
import com.unixtools.core.Command;
4+
import java.io.IOException;
5+
import java.nio.file.*;
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
import java.util.Scanner;
9+
10+
public class MvCommand implements Command {
11+
private static final String VALID_FLAGS = "ivb";
12+
private final Scanner scanner = new Scanner(System.in);
13+
14+
@Override
15+
public void execute(String[] args) {
16+
List<String> flags = new ArrayList<>();
17+
List<String> paths = new ArrayList<>();
18+
19+
parseArguments(args, flags, paths);
20+
if (!areFlagsValid(flags)) {
21+
System.out.println("Invalid usage. Valid flags are: " + VALID_FLAGS);
22+
return;
23+
}
24+
if (paths.size() != 2) {
25+
System.out.println("Invalid usage. Two paths required: source and destination.");
26+
return;
27+
}
28+
29+
String sourcePath = normalizePath(paths.get(0));
30+
String destinationPath = normalizePath(paths.get(1));
31+
boolean interactive = flags.contains("i");
32+
boolean verbose = flags.contains("v");
33+
boolean backup = flags.contains("b");
34+
35+
try {
36+
movePath(Paths.get(sourcePath), Paths.get(destinationPath), interactive, verbose, backup);
37+
} catch (IOException e) {
38+
System.out.println("mv: error occurred - " + e.getMessage());
39+
}
40+
}
41+
42+
private void parseArguments(String[] args, List<String> flags, List<String> paths) {
43+
for (String arg : args) {
44+
if (arg.startsWith("-")) {
45+
for (char flag : arg.substring(1).toCharArray()) {
46+
flags.add(String.valueOf(flag));
47+
}
48+
} else {
49+
paths.add(arg);
50+
}
51+
}
52+
}
53+
54+
private boolean areFlagsValid(List<String> flags) {
55+
return flags.stream().allMatch(flag -> VALID_FLAGS.contains(flag.replace("-", "")));
56+
}
57+
58+
private void movePath(Path source, Path destination, boolean interactive, boolean verbose, boolean backup)
59+
throws IOException {
60+
if (!Files.exists(source)) {
61+
System.out.println("mv: '" + source + "' does not exist");
62+
return;
63+
}
64+
65+
if (Files.isDirectory(source) && Files.isRegularFile(destination)) {
66+
System.out.println("mv: cannot overwrite non-directory '" + destination + "' with directory '" + source + "'");
67+
return;
68+
}
69+
70+
if (Files.exists(destination) && !Files.isDirectory(destination)) {
71+
if (!interactive || !confirmOverwrite(destination)) {
72+
return;
73+
}
74+
if (backup) {
75+
createBackup(destination);
76+
}
77+
} else if (Files.isDirectory(destination)) {
78+
destination = destination.resolve(source.getFileName());
79+
}
80+
81+
Files.move(source, destination, StandardCopyOption.REPLACE_EXISTING);
82+
if (verbose) {
83+
System.out.println("mv: moved '" + source + "' to '" + destination + "'");
84+
}
85+
}
86+
87+
private boolean confirmOverwrite(Path file) {
88+
System.out.print("mv: overwrite '" + file + "'? (y/n) ");
89+
String response = scanner.nextLine();
90+
return response.equalsIgnoreCase("y");
91+
}
92+
93+
private void createBackup(Path file) throws IOException {
94+
Path backupPath = Paths.get(file.toString() + "~");
95+
Files.copy(file, backupPath, StandardCopyOption.REPLACE_EXISTING);
96+
}
97+
98+
private String normalizePath(String path) {
99+
String normalizedPath = path.replace("\\", "/");
100+
Path pathObj = Paths.get(normalizedPath).normalize();
101+
return pathObj.toString();
102+
}
5103
}
Lines changed: 106 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,109 @@
11
package com.unixtools.command.filemanagement;
22

3-
public class RmCommand {
4-
3+
import com.unixtools.core.Command;
4+
import java.io.*;
5+
import java.nio.file.*;
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
import java.util.Scanner;
9+
10+
public class RmCommand implements Command {
11+
private static final String VALID_FLAGS = "rfi";
12+
private final Scanner scanner = new Scanner(System.in);
13+
14+
@Override
15+
public void execute(String[] args) {
16+
List<String> flags = new ArrayList<>();
17+
List<String> paths = new ArrayList<>();
18+
19+
parseArguments(args, flags, paths);
20+
if (!areFlagsValid(flags)) {
21+
System.out.println("Invalid usage. Valid flags are: " + VALID_FLAGS);
22+
return;
23+
}
24+
25+
boolean recursive = flags.contains("r");
26+
boolean force = flags.contains("f");
27+
boolean interactive = flags.contains("i");
28+
29+
for (String path : paths) {
30+
Path normalizedPath = Paths.get(normalizePath(path));
31+
try {
32+
removePath(normalizedPath, recursive, force, interactive);
33+
} catch (IOException e) {
34+
if (!force) {
35+
System.out.println("rm: error occurred - " + e.getMessage());
36+
}
37+
}
38+
}
39+
}
40+
41+
private void parseArguments(String[] args, List<String> flags, List<String> paths) {
42+
for (String arg : args) {
43+
if (arg.startsWith("-")) {
44+
for (char flag : arg.substring(1).toCharArray()) {
45+
flags.add(String.valueOf(flag));
46+
}
47+
} else {
48+
paths.add(arg);
49+
}
50+
}
51+
}
52+
53+
private boolean areFlagsValid(List<String> flags) {
54+
return flags.stream().allMatch(flag -> VALID_FLAGS.contains(flag.replace("-", "")));
55+
}
56+
57+
private void removePath(Path path, boolean recursive, boolean force, boolean interactive) throws IOException {
58+
File file = path.toFile();
59+
if (!file.exists()) {
60+
if (!force) {
61+
System.out.println("rm: cannot remove '" + path + "': No such file or directory");
62+
}
63+
return;
64+
}
65+
66+
if (file.isDirectory()) {
67+
if (!recursive && file.list().length > 0) {
68+
System.out.println("rm: cannot remove '" + path + "': Is a directory without -r flag");
69+
return;
70+
}
71+
if (interactive && !confirmRemoval(path)) {
72+
return;
73+
}
74+
removeDirectory(file, recursive, force, interactive);
75+
} else {
76+
if (interactive && !confirmRemoval(path)) {
77+
return;
78+
}
79+
Files.delete(path);
80+
}
81+
}
82+
83+
private void removeDirectory(File directory, boolean recursive, boolean force, boolean interactive)
84+
throws IOException {
85+
if (recursive) {
86+
File[] files = directory.listFiles();
87+
if (files != null) {
88+
for (File file : files) {
89+
removePath(file.toPath(), true, force, interactive);
90+
}
91+
}
92+
}
93+
if (!interactive || confirmRemoval(directory.toPath())) {
94+
Files.delete(directory.toPath());
95+
}
96+
}
97+
98+
private boolean confirmRemoval(Path path) {
99+
System.out.print("rm: remove '" + path + "'? (y/n) ");
100+
String response = scanner.nextLine();
101+
return response.equalsIgnoreCase("y");
102+
}
103+
104+
private String normalizePath(String path) {
105+
String normalizedPath = path.replace("\\", "/");
106+
Path pathObj = Paths.get(normalizedPath).normalize();
107+
return pathObj.toString();
108+
}
5109
}

src/com/unixtools/core/CommandFactory.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ public static Command getCommand(String commandName) {
1111
return new MkdirCommand();
1212
case "rmdir":
1313
return new RmdirCommand();
14+
case "cp":
15+
return new CpCommand();
16+
case "rm":
17+
return new RmCommand();
18+
case "mv":
19+
return new MvCommand();
1420
default:
1521
return null;
1622
}

0 commit comments

Comments
 (0)