Friday, January 1, 2010

Finding Files by Name with Groovy

I recently was trying unsuccessfully to burn some files to a DVD with my Vista-based laptop. Thanks to a Google search, I found a helpful page at TroubleFixers.com that indicated that this particular error might be caused by a dollar sign ($) in a filename extension or by the machine going into sleep mode during a mastered disc writing. Because I was having difficulty getting the Vista search to do what I wanted (probably more my fault than Vista's), I turned to a Groovy solution for finding files with $ in their name.

fileFind.groovy

#!/usr/bin/env groovy
// fileFind.groovy
//
// Find a file with recursive directory search.
//
// There are certain rules to be observed when providing the substring to be
// searched for in file names:
// Escape the $ character with a slash.
//
if (args.length < 2)
{
println "Need to specify directory to be searched and the substring of file."
println "\tUSAGE: fileFind <directoryPath> <fileNameSubString>"
System.exit(-1)
}
def directoryName = args[0]
def fileSubStr = args[1]
def filePattern = ~/${fileSubStr}/
def directory = new File(directoryName)
if (!directory.isDirectory())
{
println "The provided directory name ${directoryName} is NOT a directory."
System.exit(-2)
}
println "Searching for files including ${fileSubStr} in directory ${directoryName}..."
def findFilenameClosure =
{
if (filePattern.matcher(it.name).find())
{
println "\t${it.name} (size ${it.size()})"
}
}
println "Matching Files:"
directory.eachFileRecurse(findFilenameClosure)


The above script will print out the name of any file it finds matching the provided string. If I pass $ to it without escaping the dollar sign, all files in the directory are returned. Using backslash to escape the dollar sign accomplishes what I want (only files with $ in their name). The next two screen snapshots demonstrate this.

Finding All Files with Unescaped $



Finding Only Files with $ in Their Name




If the purpose is to delete these files that match, that is very easy to add to the above script. In a "production" quality script, I'd add some optional deletion verification. For now, I'm going to live on the edge and add capability to automatically and without verification delete the matching files. Don't try this at home!

fileFindAndDelete.groovy

#!/usr/bin/env groovy
// fileFindAndDelete.groovy
//
// Find a file with recursive directory search and delete any matching files.
//
// There are certain rules to be observed when providing the substring to be
// searched for in file names:
// Escape the $ character with a slash.
//
if (args.length < 2)
{
println "Need to specify directory to be searched and the substring of file."
println "\tUSAGE: fileFind <directoryPath> <fileNameSubString>"
System.exit(-1)
}
def directoryName = args[0]
def fileSubStr = args[1]
def filePattern = ~/${fileSubStr}/
def directory = new File(directoryName)
if (!directory.isDirectory())
{
println "The provided directory name ${directoryName} is NOT a directory."
System.exit(-2)
}
println "Searching for files including ${fileSubStr} in directory ${directoryName}..."
def findFilenameClosure =
{
if (filePattern.matcher(it.name).find())
{
println "\tDeleting ${it.name} (size ${it.size()}) ..."
it.delete()
println "\t${it.name} deleted."
}
}
println "Matching Files:"
directory.eachFileRecurse(findFilenameClosure)


I simply changed the closure to delete the files with matching names. The output of this script looks like shown in the next screen snapshot.

Find and Delete Files Matching Name via Groovy




The above scripts took advantage of Java APIs (such as java.io.File and Java regular expressions support with classes like java.util.regex.Matcher) and Groovy goodness (such as Groovy's GDK-provided File support, Groovy's regular expression support, closures, and more concise syntax).


Conclusion

Groovy is so easy to apply that it didn't take me much longer to write and use a Groovy script to delete the necessary files than it would have taken me to figure out how to do the same thing via Windows and then delete each of those found files. This was a situation where scripting works better than manual handling and Groovy makes that scripting easy.

No comments: