This episode takes you into the world of Groovy scripting for task automation: parsing command-line arguments, reading environment variables, file handling, text processing, and managing log output. You will build a CLI script ready for production use.

Groovy was born for scripting, and this episode is the most direct manifestation of that purpose. You'll learn to write scripts that can be run from the terminal to automate repetitive tasks — from processing files to checking system conditions.
Episode 8 covers parsing command-line arguments, reading environment variables, file handling, text processing, and log output. After this episode, you'll create clean CLI scripts that are ready for production.
Every Groovy script has an args variable containing the command-line arguments:
println "Jumlah argumen: ${args.length}"
args.each { arg ->
println "Argumen: ${arg}"
}Run it with:
groovy script.groovy halo duniagroovy script.groovy halo dunia passes halo and dunia to the args variable. This args variable is available automatically in every script, without any declaration.
For more complex scripts, you can process arguments manually:
def mode = "dev"
def nama = "Teman"
for (i in 0..<args.length) {
if (args[i] == "--mode" && i + 1 < args.length) {
mode = args[i + 1]
} else if (args[i] == "--nama") {
nama = args[i + 1]
}
}
println "Mode: ${mode}, Nama: ${nama}"for (i in 0..<args.length) iterates over the arguments and checks the flags. This manual pattern is enough for small scripts; for mature option parsing, you can use Apache's commons-cli library.
Scripts often need to read configuration from the environment:
def home = System.getenv("HOME")
println "Home directory: ${home}"
def apiKey = System.getenv("API_KEY") ?: "tidak-ada"
println "API key tersedia: ${apiKey != "tidak-ada"}"System.getenv("HOME") reads an environment variable. The Elvis operator ?: provides a default value when the variable isn't set, so the script doesn't crash due to a different environment.
In addition to the environment, Groovy can read JVM system properties passed when running Java:
def region = System.getProperty("region", "ap-southeast-1")
println "Region: ${region}"Run it with:
groovy -Dregion=us-east-1 script.groovygroovy -Dregion=us-east-1 script.groovy passes the region system property, and System.getProperty("region", "ap-southeast-1") reads it with a default fallback. These two configuration sources — environment and properties — will be managed further in episode 14.
The Groovy JDK makes file operations very concise:
def input = new File("/tmp/sumber.txt")
def output = new File("/tmp/hasil.txt")
output.text = input.text.toUpperCase()
println "Isi asli: ${input.text}"
println "Isi hasil: ${output.text}"input.text reads the entire file contents as a string, and output.text = ... writes it all at once. input.text.toUpperCase() combines string enhancements with file operations in a single line.
For large files, process line by line to save memory:
new File("/tmp/log.txt").eachLine { baris, nomor ->
if (baris.contains("ERROR")) {
println "${nomor}: ${baris}"
}
}new File("/tmp/log.txt").eachLine { baris, nomor -> ... } iterates over each line with its number, and only prints the lines containing ERROR. This pattern is ideal for filtering logs or structured data.
For more complex matching, Groovy supports regex with slash literals, for example /(?i)error\s+\d+/, so you don't need excessive backslash escaping like in Java.
Production scripts need logs that are easy for machines to read:
def log(String level, String pesan) {
def waktu = new Date().format("yyyy-MM-dd HH:mm:ss")
println "${waktu} [${level}] ${pesan}"
}
log("INFO", "Script dimulai")
log("WARN", "Cache belum ada, memuat ulang")
log("ERROR", "Gagal menghubungi API")new Date().format("yyyy-MM-dd HH:mm:ss") adds a timestamp, and log("INFO", "...") produces a consistent log line. This format is easy for observability tools to parse, which we'll cover in episode 19.
Let's bring all the concepts together in one complete script:
def folder = System.getenv("LOG_DIR") ?: "/tmp/logs"
def pola = /\.log$/
def totalError = 0
new File(folder).listFiles().findAll { it.name ==~ pola }.each { file ->
def errors = file.text.readLines().findAll { it.contains("ERROR") }
totalError += errors.size()
println "${file.name}: ${errors.size()} error"
}
println "Total error: ${totalError}"new File(folder).listFiles().findAll { it.name ==~ pola } finds all .log files in the directory, then counts the ERROR lines in each file. This script shows how file handling, regex, environment, and collections work together in one complete program.
Episode 8 made you productive as a script writer: reading arguments with args, reading environment variables and system properties, processing files and text, and writing structured logs.
The key takeaways:
args variable automatically holds the command-line arguments.System.getenv reads the environment; System.getProperty reads JVM properties.file.text reads and writes an entire file's contents.eachLine processes large files line by line without wasting memory./regex/ eliminate the need for excessive escaping.In episode 9 next, we'll discuss DSLs and domain-specific languages — the principles of building DSLs in Groovy, builder-style DSLs, declarative configuration, and DSL examples for deployment and testing.