Program: Find

This program implements a small subset of the MS-Windows Find Filesdialog or the Unix find command. However, it has much of the structure needed to build a more complete version of either of these. It uses a custom filename filter controlled by the -n command-line option, which is parsed using my GetOpt (see Section 2.8).

import com.darwinsys.util.*;
import java.io.*;
import java.io.*;

/**
 * Find - find files by name, size, or other criteria. Non-GUI version.
 */
public class Find {
    /** Main program */
    public static void main(String[] args) {
        Find finder = new Find(  );
        GetOpt argHandler = new GetOpt("n:s:");
        int c;
        while ((c = argHandler.getopt(args)) != GetOpt.DONE) {
            switch(c) {
            case 'n': finder.filter.setNameFilter(argHandler.optarg(  )); break;
            case 's': finder.filter.setSizeFilter(argHandler.optarg(  )); break;
            default:    
                System.out.println("Got: " + c);
                usage(  );
            }
        }
        if (args.length == 0 || argHandler.getOptInd(  )-1 == args.length) {
            finder.doName(".");
        } else {
            for (int i = argHandler.getOptInd(  )-1; i<args.length; i++)
                finder.doName(args[i]);
        }
    }

    protected FindFilter filter = new FindFilter(  );

    public static void usage(  ) {
        System.err.println(
            "Usage: Find [-n namefilter][-s sizefilter][dir...]");
        System.exit(1);
    }

    /** doName - handle one filesystem object by name */
    private void doName(String s) {
        Debug.println("flow", "doName(" + s + ")");
        File f = new File(s);
        if (!f.exists(  )) {
            System.out.println(s + " does not exist");
            return;
        }
        if (f.isFile(  ))
            doFile(f);
        else if (f.isDirectory(  )) {
            // System.out.println("d " + f.getPath(  ));
            String objects[] = f.list(filter);

            for (int i=0; i<objects.length; i++)
                doName(s + f.separator + objects[i]);
        } else
            System.err.println("Unknown type: " + s);
    }

    /** doFile - process one regular file. */
    private static void doFile(File f) {
        System.out.println("f " + f.getPath(  ));
    }
}

The program uses a class called FindFilter to implement matching:

import java.io.*;
import org.apache.regexp.*;
import com.darwinsys.util.Debug;

/** Class to encapsulate the filtration for Find.
 * For now just setTTTFilter(  ) methods. Really needs to be a real
 * data structure to allow complex things like
 *        -n "*.html" -a ( -size < 0 -o mtime < 5 ).
 */
public class FindFilter implements FilenameFilter {
    boolean sizeSet;
    int size;
    String name;
    RE nameRE;

    public FindFilter(  ) {
    }

    void setSizeFilter(String sizeFilter) {
        size = Integer.parseInt(sizeFilter);
        sizeSet = true;
    }

    /** Convert the given shell wildcard pattern into internal form (an RE) */
    void setNameFilter(String nameFilter) {
        name = nameFilter;
        StringBuffer sb = new StringBuffer('^'),
        for (int i = 0; i < nameFilter.length(  ); i++) {
            char c = nameFilter.charAt(i);
            switch(c) {
                case '.':    sb.append("\."); break;
                case '*':    sb.append(".*"); break;
                case '?':    sb.append('.'), break;
                default:    sb.append(c); break;
            }
        }
        sb.append('$'),
        Debug.println("name", "RE="" + sb + "".");
        try {
            nameRE = new RE(sb.toString(  ));
        } catch (RESyntaxException ex) {
            System.err.println("For shame! " + ex);
        }
    }

    /** Do the filtering. For now, only filter on name */
    public boolean accept(File dir, String fileName) {
        File f = new File(dir, fileName);
        if (f.isDirectory(  )) {
            return true;    // allow recursion
        }

        if (name != null) {
            return nameRE.match(fileName);
        }

        // TODO size handling.

        // Catchall
        return false;
    }
}

Exercise for the reader: in the source directory, you’ll find a class called FindNumFilter, which is meant to (someday) allow relational comparison of sizes, modification times, and the like, as most find services already offer. Make this work from the command line, and write a GUI front-end to this program.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.21.12.140