Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Andrey Adamovich - Groovy 2 Cookbook - 2013.pdf
Скачиваний:
44
Добавлен:
19.03.2016
Размер:
26.28 Mб
Скачать

Chapter 4

Deleting a file or directory

Deleting a file or directory may seem a trivial task and it often is, but it has some hidden quirks that Groovy may help you with. This recipe will enlist and give details about several methods to delete a file or a directory.

Getting ready

Let's assume that we have two java.io.File variables: one pointing to a normal file and another to a nonempty directory with several subdirectories in it. For example:

def dir = new File('./tmp1')

def file = new File('./tmp2/test.txt')

As you know from Java, the java.io.File class has a delete method and it works perfectly in many situations. But it will only delete a normal file or an empty directory. So, to delete a nonempty directory you need to write a recursive function in Java. Also, in most of the situations, the delete method will not throw any exceptions; it will just return false if it fails to delete a file or directory.

How to do it...

Let's explore several ways to delete things on the file system.

1.To delete the nonempty directories, Groovy provides an extension method deleteDir in the java.io.File class. Let's try to delete our file and directory with both the delete and deleteDir methods and print the result:

println file.deleteDir() println file.delete() println dir.delete() println dir.deleteDir()

2.The previous code snippet should give the following output:

false true false true

How it works...

The first method call returns false, because the given file is not a directory. The second one successfully deletes the file and returns true. The third one returns false because we try to delete a nonempty directory. The last one returns true, because we recursively delete the root folder and its subfolders with the Groovy's deleteDir method.

149

www.it-ebooks.info

Working with Files in Groovy

In order to ensure that a file or a directory is deleted, you always need to check the result of the delete or deleteDir method. In a scenario where several files or folders have to be deleted, you may end up with a lot of noisy conditional statements. Not pretty. An elegant solution to the issue posed above is possible by resorting to Groovy's metaprogramming features. The java.io.File class can be enhanced with a new method, safeDelete:

File.metaClass.safeDelete = { if (exists()) {

if (isDirectory()) { if (!deleteDir()) {

def msg = "Unable to delete a directory: ${name}" throw new IOException(msg)

}

}else {

if (!delete()) {

def msg = "Unable to delete a file: ${name}" throw new IOException(msg)

}

}

}

}

Groovy metaprogramming and the metaClass object are discussed in more detail in

Chapter 9, Metaprogramming and DSLs in Groovy. In short, the previous code adds a new method to the java.io.File class called safeDelete. The new method ensures that the file exists; then it checks if the File is a directory, and calls a recursive delete on it. If the

File object points to a file, it calls a normal delete. If either the delete or deleteDir operations return false, the method throws an IOException.

After you have extended the java.io.File class, then you can simply call the method on any File instance:

file.safeDelete()

dir.safeDelete()

By using this method, you can avoid many conditional statements and implement simpler exception handling.

There's more...

One more way to manipulate files is by using Groovy's built-in Apache Ant support. Through the groovy.util.AntBuilder class, you can get access to all the common Ant tasks including the delete task.

def ant = new AntBuilder()

ant.delete(dir: file.absolutePath, failonerror:false)

150

www.it-ebooks.info

Chapter 4

Ant's file-handling capabilities are quite extended, especially when it comes to copying files around.

See also

ff Chapter 9, Metaprogramming and DSLs in Groovy

ff http://groovy.codehaus.org/Using+Ant+from+Groovy

ff http://groovy.codehaus.org/api/groovy/util/AntBuilder.html

Walking through a directory recursively

Hierarchical file systems are the way we store most of our data. Groovy can help to build code that needs to go through a dense forest of directory trees.

In this recipe, we will cover different ways of walking through a directory tree using Groovy I/O awesomeness.

Getting ready

Let's assume that we need to walk through the current working directory. We can define the currentDir variable of java.io.File type that points to it:

def currentDir = new File('.')

To test this recipe, you can use either a script file that you launch with the groovy command or the groovysh/groovyConsole prompt.

How to do it...

As you probably know, the java.io.File class already provides the list and listFiles methods that return a collection of first-level elements (files and directories) in a directory represented by a File object. Using a recursive function, you can easily traverse the subfolders found in the first-level folders.

1.However, Groovy already provides more concise methods that use recursion internally to traverse a directory. One of them is the eachFileRecurse method. It takes a closure as an input parameter, which is called for every file or directory entry that

is found:

currentDir.eachFileRecurse { File file -> println file.name

}

151

www.it-ebooks.info

Working with Files in Groovy

2.If you need to walk recursively only through the directories, then you can use the eachDirRecurse method instead:

currentDir.eachDirRecurse { File dir -> println dir.name

}

3.If you only need to go through the files, then you can pass an additional parameter to eachFileRecurse, which is a value of a groovy.io.FileType enumeration (you'll need to add an additional import at the beginning of your script or groovysh/ groovyConsole prompt):

import groovy.io.FileType

...

currentDir.eachFileRecurse(FileType.FILES) { File file -> println file.name

}

How it works...

The previous code recursively prints the names of all the files and/or directories in the current directory tree. The recursive walk performs a depth-first search. That means that when the search goes through a list of children and encounters a directory, then it goes (deeper) inside that directory first before returning to process the remaining children. The order in which files and directories are processed depends on the implementation of the file system.

There's more...

Groovy also adds the eachFile and eachDir methods to a java.io.File class that you can use to iterate through the first-level elements only (just like listFiles). As other eachmethods, they take a closure as an input parameter. You can use that to build a recursive function in a similar way as you would use it with the listFiles method. But instead of defining a separate function, you can also make use of Groovy's closure that is capable of creating a copy of itself with the help of the trampoline method:

currentDir.eachFile { File file -> println file.name

if (file.isDirectory()) { file.eachFile( trampoline() )

}

}

The code snippet above does exactly the same thing as the previous code examples. The "magic" trampoline method passes a copy of the parent closure to the nested eachFile call, a copy of the parent closure and makes it behave like a recursive function.

152

www.it-ebooks.info

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]