|
From: <ls...@us...> - 2009-04-01 15:03:34
|
Revision: 5208
http://jnode.svn.sourceforge.net/jnode/?rev=5208&view=rev
Author: lsantha
Date: 2009-04-01 15:03:30 +0000 (Wed, 01 Apr 2009)
Log Message:
-----------
'find' command implementation - by Alexander Kerner
Modified Paths:
--------------
trunk/fs/descriptors/org.jnode.fs.command.xml
Added Paths:
-----------
trunk/fs/src/fs/org/jnode/fs/command/AbstractDirectoryWalker.java
trunk/fs/src/fs/org/jnode/fs/command/FindCommand.java
Modified: trunk/fs/descriptors/org.jnode.fs.command.xml
===================================================================
--- trunk/fs/descriptors/org.jnode.fs.command.xml 2009-04-01 13:44:48 UTC (rev 5207)
+++ trunk/fs/descriptors/org.jnode.fs.command.xml 2009-04-01 15:03:30 UTC (rev 5208)
@@ -33,6 +33,7 @@
<alias name="touch" class="org.jnode.fs.command.TouchCommand"/>
<alias name="hexdump" class="org.jnode.fs.command.HexdumpCommand"/>
<alias name="md5sum" class="org.jnode.fs.command.Md5SumCommand"/>
+ <alias name="find" class="org.jnode.fs.command.FindCommand"/>
</extension>
<extension point="org.jnode.shell.syntaxes">
@@ -112,6 +113,20 @@
<syntax alias="touch">
<argument argLabel="file" description="touch the given file"/>
</syntax>
+ <syntax alias="find">
+ <sequence description="find files or directories">
+ <repeat minCount="1">
+ <argument argLabel="directory"/>
+ </repeat>
+ <optionSet>
+ <option argLabel="type" longName="type"/>
+ <option argLabel="maxdepth" longName="maxdepth"/>
+ <option argLabel="mindepth" longName="mindepth"/>
+ <option argLabel="name" longName="name"/>
+ <option argLabel="iname" longName="iname"/>
+ </optionSet>
+ </sequence>
+ </syntax>
</extension>
<extension point="org.jnode.security.permissions">
Added: trunk/fs/src/fs/org/jnode/fs/command/AbstractDirectoryWalker.java
===================================================================
--- trunk/fs/src/fs/org/jnode/fs/command/AbstractDirectoryWalker.java (rev 0)
+++ trunk/fs/src/fs/org/jnode/fs/command/AbstractDirectoryWalker.java 2009-04-01 15:03:30 UTC (rev 5208)
@@ -0,0 +1,113 @@
+package org.jnode.fs.command;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.Stack;
+
+public abstract class AbstractDirectoryWalker {
+
+ private class FileObject {
+ final File file;
+ final Long depth;
+
+ FileObject(File file, Long depth) {
+ this.file = file;
+ this.depth = depth;
+ }
+ }
+
+ private final Stack<FileObject> stack = new Stack<FileObject>();
+ private final Set<FileFilter> filters = new HashSet<FileFilter>();
+ private volatile boolean cancelled = false;
+ private volatile Long maxDepth = null;
+ private volatile Long minDepth = null;
+
+ public synchronized void walk(final File... dirs) throws IOException {
+ for (File dir : dirs) {
+ if (dir == null)
+ throw new IOException("No such directroy " + dir);
+ dir = dir.getAbsoluteFile(); // to be able to handle relative paths
+ if (!dir.canRead() || !dir.isDirectory()) {
+ throw new IOException("Cannot read directroy " + dir);
+ }
+ stack.push(new FileObject(dir, 0L));
+ while (!cancelled && !stack.isEmpty()) {
+ go1(stack.pop());
+ }
+ }
+ }
+
+ private void go1(final FileObject file) throws IOException {
+ if ((minDepth != null && file.depth < minDepth) || (maxDepth != null && file.depth > maxDepth)) {
+ // out of boundaries
+ } else if (!file.file.canRead()) {
+ // ignore for now
+ } else if (validFileOrDirectory(file)) {
+ handleFileOrDir(file);
+ } else {
+ // filtered out
+ }
+ go2(file);
+ }
+
+ private void go2(final FileObject file) throws IOException {
+ final Stack<File> stack = new Stack<File>();
+ final File[] content = file.file.listFiles();
+ if (content != null) {
+ for (File f : content) {
+ if (f.toString().equals(f.getCanonicalPath())) {
+ stack.push(f);
+ } else {
+ // dont follow symlinks
+ }
+ }
+ while (!stack.isEmpty()) {
+ File tmp = stack.pop();
+ // addToStack(stack.pop(), file.depth + 1);
+ this.stack.push(new FileObject(tmp, file.depth + 1));
+ }
+ }
+ }
+
+ private void handleFileOrDir(final FileObject file) {
+ if (file.file.isDirectory())
+ handleDir(file.file);
+ else if (file.file.isFile())
+ handleFile(file.file);
+ else {
+ // ignore unknown file type
+ }
+ }
+
+ private boolean validFileOrDirectory(final FileObject file) {
+ if (!filters.isEmpty())
+ for (FileFilter filter : filters)
+ if (!filter.accept(file.file))
+ return false;
+ return true;
+ }
+
+ public void stoppWalking() {
+ cancelled = true;
+ }
+
+ public void setMinDepth(Long min) {
+ minDepth = min;
+ }
+
+ public void setMaxDepth(Long max) {
+ maxDepth = max;
+ }
+
+ public synchronized void addFilter(FileFilter filter) {
+ filters.add(filter);
+ }
+
+ public abstract void handleDir(File f);
+
+ public abstract void handleFile(File f);
+
+}
Added: trunk/fs/src/fs/org/jnode/fs/command/FindCommand.java
===================================================================
--- trunk/fs/src/fs/org/jnode/fs/command/FindCommand.java (rev 0)
+++ trunk/fs/src/fs/org/jnode/fs/command/FindCommand.java 2009-04-01 15:03:30 UTC (rev 5208)
@@ -0,0 +1,108 @@
+package org.jnode.fs.command;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.jnode.shell.AbstractCommand;
+import org.jnode.shell.syntax.Argument;
+import org.jnode.shell.syntax.FileArgument;
+import org.jnode.shell.syntax.LongArgument;
+import org.jnode.shell.syntax.StringArgument;
+
+public class FindCommand extends AbstractCommand {
+
+ private class Walker extends AbstractDirectoryWalker {
+
+ @Override
+ public void handleDir(File f) {
+ out.println(f);
+ }
+
+ @Override
+ public void handleFile(File f) {
+ out.println(f);
+ }
+
+ }
+
+ private final StringArgument nameArg = new StringArgument("name", Argument.OPTIONAL);
+ private final StringArgument inameArg = new StringArgument("iname", Argument.OPTIONAL);
+ private final LongArgument maxdepthArg = new LongArgument("maxdepth", Argument.OPTIONAL);
+ private final LongArgument mindepthArg = new LongArgument("mindepth", Argument.OPTIONAL);
+ private final StringArgument typeArg = new StringArgument("type", Argument.OPTIONAL);
+ private final FileArgument dirArg =
+ new FileArgument("directory", Argument.MANDATORY | Argument.EXISTING
+ | Argument.MULTIPLE);
+ private PrintWriter out = null;
+
+ public FindCommand() {
+ super("Find files and directories");
+ registerArguments(dirArg, mindepthArg, maxdepthArg, inameArg, nameArg, typeArg);
+ }
+
+ public static void main(String[] args) throws IOException {
+
+ new FindCommand().execute();
+ }
+
+ public void execute() throws IOException {
+ out = getOutput().getPrintWriter();
+ final Walker walker = new Walker();
+
+ if (maxdepthArg.isSet()) {
+ walker.setMaxDepth(maxdepthArg.getValue());
+ }
+
+ if (mindepthArg.isSet()) {
+ walker.setMinDepth(mindepthArg.getValue());
+ }
+
+ if (nameArg.isSet()) {
+ final String value = nameArg.getValue();
+ walker.addFilter(new FileFilter() {
+ @Override
+ public boolean accept(File file) {
+ Pattern p = Pattern.compile(value);
+ Matcher m = p.matcher(file.getName());
+ return m.matches();
+ }
+ });
+ }
+
+ if (inameArg.isSet()) {
+ final String value = inameArg.getValue();
+ walker.addFilter(new FileFilter() {
+ @Override
+ public boolean accept(File file) {
+ Pattern p = Pattern.compile(value, Pattern.CASE_INSENSITIVE);
+ Matcher m = p.matcher(file.getName());
+ return m.matches();
+ }
+ });
+ }
+
+ if (typeArg.isSet()) {
+ final Character value = typeArg.getValue().charAt(0);
+ if (value.equals(Character.valueOf('f'))) {
+ walker.addFilter(new FileFilter() {
+ @Override
+ public boolean accept(File file) {
+ return file.isFile();
+ }
+ });
+ } else if (value.equals(Character.valueOf('d'))) {
+ walker.addFilter(new FileFilter() {
+ @Override
+ public boolean accept(File file) {
+ return file.isDirectory();
+ }
+ });
+ }
+ }
+ walker.walk(dirArg.getValues());
+ }
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|