0

So I'm trying to create a program in Unix that will take in a directory as a parameter and then recursively go through, open all of the folders, look through all of the files, and then delete all of the class files. I thought I was taking the correct steps as I was given code for a similar program and told to use it as a basis, but upon testing my program and I discover that nothing happens.

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.ParseException;

public class ClassFileDeleter {
    public static void main(String[] args) throws ParseException {
    String dirName = args[0];
    deleteFile(dirName);
}

private static void deleteFile(String dirName) {
    Path path = Paths.get(dirName);
    File dir = path.toFile();

    if(dir.exists()) {
    File[] files = dir.listFiles();
    if(dir.isDirectory()) {
    for(File f:files) {
    if(!f.isDirectory())
            if(f.toString().endsWith(".class"))
            System.out.println("yes");
            else deleteFile(dirName + "/" + f.getName());

    }}}
    }}

I am at a loss at what I should do. I haven't attempted to delete anything yet because I don't want to delete anything that isn't a class file so I am using some dummy code that should print 'yes' once the program finds a class file. However when I run my code, absolutely nothing happens. I believe that there is either an issue with the way I am searching for class files (We are supposed to use endsWith) or with the way I am attempting to use recursion to look through all of the files in the specified directory. If I could have some assistance, that would be great.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Jake
  • 23
  • 3
  • wouldn't this be simpler with bash? – Neilos Mar 18 '15 at 23:02
  • Ah yes, I feel as though it can be done with bash quite simply, but the task is to write a java program that is able to achieve the same functionality. – Jake Mar 18 '15 at 23:04
  • oh ok, just seems a little overkill :) – Neilos Mar 18 '15 at 23:05
  • 1
    `Runtime.exec("sh -c find . -name '*.class' -exec rm '{}' -print");` ;-) – user207421 Mar 18 '15 at 23:07
  • It has to be done in Java :( – Jake Mar 18 '15 at 23:08
  • @Jake Why does it have to be done in Java? – Elliott Frisch Mar 18 '15 at 23:10
  • Can you use commons-io? The commons stuff is pretty standard, I don't start a project without it. – Neilos Mar 18 '15 at 23:11
  • http://stackoverflow.com/questions/3154488/best-way-to-iterate-through-a-directory-in-java here is an idea of how to go through the directories... But if the filesystem is huge you might run out of memory as the loops just go deeper and deeper... There are more efficient ways to achieve it, like always more than one way to skin a cat but what are your limitations? – Neilos Mar 18 '15 at 23:13
  • @ElliottFrisch it has to be done in Java because its to see our ability in using IO/NIO and recursion. – Jake Mar 18 '15 at 23:14
  • @Neilos : O! Thanks, I believe I see what my error was. Let me just try to change something around in the code real quick. And as for our limitations, we are to use java and only draw upon the methods from the imports I have listed in the original question. – Jake Mar 18 '15 at 23:28
  • By the way, this doesn't really have anything to do with PuTTY, It was that in the title that made me suggest using bash... but you're not allowed. – Neilos Mar 18 '15 at 23:37

2 Answers2

2

I would start with a isFile check (and then test the extension of a file and log it if it matches), then you could recursively descend any directories. Something like,

private static void deleteFile(String dirName) {
    File dir = new File(dirName);
    if (dir.isFile()) {
        if (dir.getName().endsWith(".class")) {
            try {
                System.out.println("Delete: " + dir.getCanonicalPath());
                // dir.delete();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    } else if (dir.isDirectory()) {
        File[] files = dir.listFiles();
        for (File f : files) {
            try {
                deleteFile(f.getCanonicalPath());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • I suspect that this answer would suffice for the OP but it is not a particularly efficient way of achieving the result. – Neilos Mar 18 '15 at 23:21
  • Oh, I think I see. So in this you first check if the directory given is a a file and then if it is you delete it but if not then you check to see if its a directory and then your recursion code is in there. My only question is that wouldn't the program stop in the event that the parameter was a class file because it would never go to the else and go through recursion? – Jake Mar 18 '15 at 23:25
  • @Jake it would go through the if and be deleted. No recursion necessary. – Elliott Frisch Mar 18 '15 at 23:29
0

It strikes me that the code that you have to recurse through the directory, is creating a file object not a directory.

A quick google gave me this from the Oracle java tutorial (http://docs.oracle.com/javase/tutorial/essential/io/dirs.html#listdir).

Listing a Directory's Contents

You can list all the contents of a directory by using the newDirectoryStream(Path) method. This method returns an object that implements the DirectoryStream interface. The class that implements the DirectoryStream interface also implements Iterable, so you can iterate through the directory stream, reading all of the objects. This approach scales well to very large directories. Remember: The returned DirectoryStream is a stream. If you are not using a try-with-resources statement, don't forget to close the stream in the finally block. The try-with-resources statement takes care of this for you.

The following code snippet shows how to print the contents of a directory:

Path dir = ...;
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
    for (Path file: stream) {
        System.out.println(file.getFileName());
    }
} catch (IOException | DirectoryIteratorException x) {
    // IOException can never be thrown by the iteration.
    // In this snippet, it can only be thrown by newDirectoryStream.
    System.err.println(x);
}

The Path objects returned by the iterator are the names of the entries resolved against the directory. So, if you are listing the contents of the /tmp directory, the entries are returned with the form /tmp/a, /tmp/b, and so on.

This method returns the entire contents of a directory: files, links, subdirectories, and hidden files. If you want to be more selective about the contents that are retrieved, you can use one of the other newDirectoryStream methods, as described later in this page.

Note that if there is an exception during directory iteration then DirectoryIteratorException is thrown with the IOException as the cause. Iterator methods cannot throw exception exceptions.

So I'd take a look there and see what you can work out.

Ben Whyall
  • 268
  • 3
  • 17
  • Thanks! I'll give that a look. Can you explain why my for loop is not recursing through? In the code we were given, the program recurses through the directories and prints out a directory tree, and it uses a for loop with files in order to do so and when I run that code, it works fine. – Jake Mar 18 '15 at 23:19
  • if (dir.exists()) { printName(layer, dir.getName()); //print dir's name, it is in the (layer)th layer File[] files = dir.listFiles(); if (dir.isDirectory()) { for (File f:files) { if (!f.isDirectory()) //f is a file under (layer)th layer directory printName(layer+1, f.getName()); else displayFile(layer+1, dirName + "/" + f.getName()); } } } – Jake Mar 18 '15 at 23:20
  • @Jake hi not sure quite why its not working as expected, it may be worth removing the filter on .class and then outputing a simple print string in the if and else to check the recurssion through the directories. – Ben Whyall Mar 18 '15 at 23:27