Skip to content

Commit dd0668e

Browse files
committed
find command with flag and path parsing
- Supports searching by name (-name) and type (-type f or -type d), along with the ability to specify a search path. - Robust argument parsing, flag validation, and concurrent searching using virtual threads for improved performance. - Handle scenarios like invalid flags, non-existent directories, and different flag orders.
1 parent 0efcb5c commit dd0668e

File tree

2 files changed

+141
-2
lines changed

2 files changed

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

3-
public class FindCommand {
4-
3+
import com.unixtools.core.Command;
4+
import java.io.File;
5+
import java.nio.file.Path;
6+
import java.nio.file.Paths;
7+
import java.util.Arrays;
8+
import java.util.HashMap;
9+
import java.util.HashSet;
10+
import java.util.Map;
11+
import java.util.Set;
12+
import java.util.concurrent.CountDownLatch;
13+
import java.util.concurrent.ExecutorService;
14+
import java.util.concurrent.Executors;
15+
16+
public class FindCommand implements Command {
17+
private static final String VALID_FLAGS = "name,type";
18+
private final ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
19+
20+
@Override
21+
public void execute(String[] args) {
22+
Map<String, String> flags = parseArguments(args);
23+
if (!validateFlags(flags.keySet())) {
24+
System.out.println("Invalid flags. Valid flags are: -name, -type");
25+
return;
26+
}
27+
28+
String searchPath = ".";
29+
if (flags.containsKey("path")) {
30+
searchPath = normalizePath(flags.get("path"));
31+
}
32+
33+
File searchDirectory = new File(searchPath);
34+
if (!searchDirectory.exists()) {
35+
System.out.println("Specified path does not exist: " + searchPath);
36+
return;
37+
}
38+
39+
String nameCriteria = flags.get("name");
40+
String typeCriteria = flags.get("type");
41+
42+
CountDownLatch latch = new CountDownLatch(1);
43+
findFiles(Paths.get(searchPath), nameCriteria, typeCriteria, latch);
44+
try {
45+
latch.await(); // Wait for all tasks to complete
46+
} catch (InterruptedException e) {
47+
System.out.println("Search interrupted.");
48+
}
49+
executor.shutdown();
50+
}
51+
52+
private Map<String, String> parseArguments(String[] args) {
53+
Map<String, String> flags = new HashMap<>();
54+
String lastFlag = null;
55+
56+
for (String arg : args) {
57+
if (arg.startsWith("-")) {
58+
lastFlag = arg.substring(1);
59+
flags.put(lastFlag, null);
60+
} else {
61+
if (lastFlag != null && flags.containsKey(lastFlag)) {
62+
flags.put(lastFlag, arg);
63+
lastFlag = null;
64+
} else {
65+
flags.put("path", normalizePath(arg));
66+
}
67+
}
68+
}
69+
return flags;
70+
}
71+
72+
private boolean validateFlags(Set<String> flagKeys) {
73+
Set<String> validFlags = new HashSet<>(Arrays.asList(VALID_FLAGS.split(",")));
74+
for (String flag : flagKeys) {
75+
if (!validFlags.contains(flag) && !flag.equals("path")) {
76+
return false;
77+
}
78+
}
79+
return true;
80+
}
81+
82+
private void findFiles(Path path, String nameCriteria, String typeCriteria, CountDownLatch latch) {
83+
executor.execute(() -> {
84+
File[] files = path.toFile().listFiles();
85+
if (files == null) {
86+
latch.countDown();
87+
return;
88+
}
89+
90+
CountDownLatch internalLatch = new CountDownLatch(files.length);
91+
for (File file : files) {
92+
if (file.isDirectory()) {
93+
if (typeCriteria == null || "d".equals(typeCriteria)) {
94+
checkAndPrintFile(file, nameCriteria, typeCriteria);
95+
}
96+
findFiles(file.toPath(), nameCriteria, typeCriteria, internalLatch);
97+
} else {
98+
if (typeCriteria == null || "f".equals(typeCriteria)) {
99+
checkAndPrintFile(file, nameCriteria, typeCriteria);
100+
}
101+
internalLatch.countDown();
102+
}
103+
}
104+
105+
try {
106+
internalLatch.await();
107+
} catch (InterruptedException e) {
108+
System.out.println("Subdirectory search interrupted.");
109+
}
110+
latch.countDown();
111+
});
112+
}
113+
114+
private void checkAndPrintFile(File file, String nameCriteria, String typeCriteria) {
115+
boolean nameMatch = (nameCriteria == null || file.getName().contains(nameCriteria));
116+
boolean typeMatch = true;
117+
118+
if (typeCriteria != null) {
119+
switch (typeCriteria) {
120+
case "f":
121+
typeMatch = file.isFile();
122+
break;
123+
case "d":
124+
typeMatch = file.isDirectory();
125+
break;
126+
}
127+
}
128+
129+
if (nameMatch && typeMatch) {
130+
System.out.println(file.getAbsolutePath());
131+
}
132+
}
133+
134+
private String normalizePath(String path) {
135+
String normalizedPath = path.replace("\\", "/");
136+
if (normalizedPath.equals(".")) {
137+
normalizedPath = Paths.get("").toAbsolutePath().toString();
138+
}
139+
Path pathObj = Paths.get(normalizedPath).normalize();
140+
return pathObj.toString();
141+
}
5142
}

src/com/unixtools/core/CommandFactory.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ public static Command getCommand(String commandName) {
2525
return new DfCommand();
2626
case "du":
2727
return new DuCommand();
28+
case "find":
29+
return new FindCommand();
2830
default:
2931
return null;
3032
}

0 commit comments

Comments
 (0)