Working with Files

Introduction

This guide covers the Fs and Compressor tools for filesystem operations and archive handling, and how to scope work to a subdirectory with cd { }.

Changing the Working Directory with cd

By default every operation inside a job runs relative to the project root. cd { } scopes a block of work to a subdirectory without affecting anything outside the block:

job {
    cd("modules/app") {
        // working directory is now modules/app
        maven.exec("package")
        // working directory is restored after the block
    }
    // back at the project root
}

The path is always relative to the current working directory, so nesting works naturally:

cd("modules") {
    cd("app") {
        // working directory is modules/app
    }
}

cd returns whatever the block returns, so you can use it to read a value from a subdirectory without affecting the rest of the job:

val version = cd("modules/app") {
    maven.getProjectVersion()
}

Working with the Filesystem

The Fs tool covers the most common filesystem operations. All paths are relative to the current working directory (respecting any enclosing cd { } block).

Creating Directories

Fs.mkdir("dist/bin")

Creates the directory and all missing parent directories. Does nothing if it already exists.

For scratch work that should be cleaned up when the job ends, create a temp directory instead:

val tmp = Fs.mktemp()
// use tmp as an absolute path
Fs.copy("build/output.zip", "$tmp/output.zip")

Copying and Moving Files

Fs.copy("target/myapp.jar", "dist/lib/myapp.jar")
Fs.move("build/report.html", "dist/report.html")

Both calls automatically create any missing parent directories at the destination.

Deleting Files

Fs.delete("build/tmp")

Deletes the path recursively if it is a directory. Does nothing if the path does not exist.

Checking Paths

if (!Fs.exists("dist/bin/myapp")) {
    fail("Launcher script was not copied")
}
val isDir = Fs.isDirectory("dist")
val isFile = Fs.isFile("dist/lib/myapp.jar")

Changing Permissions

Fs.chmod("dist/bin/myapp", "755")

Reading and Writing Files

Write a string to a file (overwrites if it already exists):

Fs.write("dist/version.txt", version)

Append to a file:

Fs.write("dist/build.log", "Build completed at $timestamp\n", append = true)

Read a file back as a string:

val properties = Fs.readAsString("config/build.properties")

Finding Files with Glob

Fs.glob finds files matching an ant-style pattern and returns their paths relative to the base directory.

Pattern syntax:

  • * matches any characters except /
  • ** matches any characters including /
  • ? matches exactly one character

Find all JARs in a target directory:

val jars = Fs.glob("target/*.jar")

Find all Java sources under src:

val sources = Fs.glob("src/**.java")

Exclude a subtree using the named-parameter form:

val xmlFiles = Fs.glob(
    includes = listOf("**.xml"),
    excludes = listOf("target/**")
)

Search relative to a different base directory:

val moduleJars = Fs.glob("**/target/*.jar", baseDir = "modules")

Find subdirectories instead of files:

val modules = Fs.glob("*", baseDir = "modules", kind = FsKind.Folder)

Packaging Archives with Compressor

Compressor creates and extracts archives. The format is detected automatically from the file extension.

Supported formats: .tar.gz / .tgz, .tar.xz / .txz, .tar.bz2 / .tbz2, .tar, .zip, .gz (single file only).

Creating an Archive

Pass a list of files or directories to include:

Compressor.compress("myapp-1.0.tar.gz", listOf("dist/"))

Use Fs.glob to select specific files:

val reports = Fs.glob("build/reports/**/*.html")
Compressor.compress("reports.zip", reports)

Extracting an Archive

Compressor.extract("downloads/tools.tar.gz", "tools/")

Use stripComponents to peel off leading path components, the same as tar --strip-components. This is useful when archives contain a top-level versioned directory:

// archive contains myapp-1.0/bin/myapp, myapp-1.0/lib/...
// stripComponents = 1 drops the myapp-1.0/ prefix
Compressor.extract("myapp-1.0.tar.gz", "dist/", stripComponents = 1)