Groovy 作為 JVM 上的動態語言,以其簡潔的語法和強大的集合處理能力,成為編寫構建腳本、自動化運維任務的利器。本文展示一個遞歸遍歷目錄並列出所有文件絕對路徑的 Groovy 腳本,並深度解析其核心 API 與函數式編程風格。
if (this.args.length) {
def dir = new File(this.args[0])
if (dir.exists() && dir.directory) {
dir.eachDirRecurse { it ->
it.listFiles().each { f ->
if (!f.directory) {
println f.absolutePath
}
}
}
} else {
println "${this.args[0]} is not a directory."
}
} else {
println "Usage: groovy ListFile.groovy "
}
| 方法/屬性 | 說明 | Groovy 增強點 |
|---|---|---|
new File(path) | 建立 File 物件 | 支援字串直接轉換,無需 new File(String) |
dir.exists() | 判斷路徑是否存在 | 同 Java |
dir.directory | 判斷是否為目錄 | 屬性存取語法,等同 isDirectory() |
dir.eachDirRecurse { ... } | 遞歸遍歷子目錄 | Groovy 獨有,內部處理遞歸邏輯,極度簡化代碼 |
it.listFiles() | 獲取目錄下所有文件/子目錄 | 返回 File[],同 Java |
.each { ... } | 集合迭代閉包 | 函數式風格,it 為隱式參數 |
f.absolutePath | 獲取文件絕對路徑 | 屬性存取語法,等同 getAbsolutePath() |
$ groovy ListFile.groovy /home/user/documents
/home/user/documents/readme.txt
/home/user/documents/project/pom.xml
/home/user/documents/project/src/main/java/App.java
/home/user/documents/notes.md
...
利用 Groovy 的集合方法鏈,可進一步簡化為單行表達式:
// 將所有文件路徑收集到列表
def files = []
new File(args[0]).eachDirRecurse { it.listFiles().each { if (!it.directory) files << it.absolutePath } }
files.each { println it }
// 或更函數式(Groovy 2.4+)
new File(args[0])
.traverse(type: groovy.io.FileType.FILES) // 僅遍歷文件
.each { println it.absolutePath }
try-catch 包裹eachDirRecurse 會跟隨符號鏈接,可能導致無限循環,生產環境需檢測循環file.encoding 一致
// Java 7+ NIO.2 版本(較冗長)
Files.walkFileTree(Paths.get(args[0]), new SimpleFileVisitor() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
System.out.println(file.toAbsolutePath());
return FileVisitResult.CONTINUE;
}
});
Groovy 版本代碼量減少 80%+,語義更直觀,極適合一次性腳本、構建任務、運維自動化場景。
本腳本展示了 Groovy 在文件系統操作上的三大優勢:
eachDirRecurse 一行搞定遞歸邏輯.each { ... } 消除迭代樣板代碼.absolutePath、.directory 更接近自然語言掌握這類 Groovy 慣用語,能讓你在 JVM 生態中以動態語言的敏捷性處理靜態語言的繁瑣任務,是 DevOps、構建工程師、後端開發者的必備技能。