Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: January 30, 2025
Jenkins is a popular automation server that helps us build, test, and deploy applications more efficiently. One of its powerful features is the Jenkins Pipeline, which defines a script-based approach for creating pipelines. Sometimes, our pipeline needs to verify the presence of a file before proceeding to the next step. For instance, we might only publish artifacts if a particular file exists, or we might want to skip certain tasks if a file is missing.
In this tutorial, we’ll explore different ways to check if a file exists in a Pipeline. We’ll discuss examples of both Declarative and Scripted Pipelines and show how to integrate these checks into real-world projects. By the end, we’ll see how Jenkins pipeline scripts can handle file checks, allowing us to control the flow of our build and deployment stages.
Before we discuss file checks, let’s briefly recap the two main pipeline styles: Declarative and Scripted.
Let’s start with the Declarative Pipeline:
Then, the Scripted Pipeline:
Regardless of our approach, a Pipeline runs on top of Groovy. This means we can tap into Groovy methods, Jenkins pipeline steps, or system commands to check for files.
Now, let’s see how we can implement various approaches to check if a file exists in Jenkins.
The simplest path in many pipelines is to rely on built-in steps, such as the fileExists step in Jenkins. This step takes a file path as input and returns a boolean. Let’s see how it looks in Scripted Pipeline:
node {
stage('Check File') {
if (fileExists('myfile.txt')) {
echo "File found."
} else {
echo "File not found."
}
}
}
This snippet runs on a node (like an agent or worker) and checks if myfile.txt exists in the workspace. If it does, we print “File found”. If not, we print “File not found”. We can extend this to more complex logic, such as skipping stages or running additional tasks if the file is there.
Sometimes, we may prefer or need to rely on system commands. This is also easy to do in Jenkins with the sh step (on Linux or macOS) or the bat step (on Windows).
For example, on Unix-based systems:
node {
stage('Shell Check') {
// Linux/macOS example
def result = sh script: '[ -f myfile.txt ] && echo "YES" || echo "NO"', returnStdout: true
if (result.trim() == "YES") {
echo "myfile.txt exists."
} else {
echo "myfile.txt missing."
}
}
}
Here we:
On Windows, we can do something similar using bat:
node {
stage('Batch Check') {
// Windows example
def result = bat script: 'if exist myfile.txt (echo YES) else (echo NO)', returnStdout: true
if (result.trim().contains("YES")) {
echo "myfile.txt exists (Windows)."
} else {
echo "myfile.txt missing (Windows)."
}
}
}
We check if myfile.txt is present using the if exist command. Then, we capture the output and parse it.
Declarative Pipelines often revolve around a pipeline block with multiple stages. We can still leverage fileExists, sh, or bat.
Let’s see a short example:
pipeline {
agent any
stages {
stage('Check File Declarative') {
steps {
script {
if (fileExists('myfile.txt')) {
echo "Found myfile.txt!"
} else {
echo "Did not find myfile.txt."
}
}
}
}
}
}
In this approach, the pipeline remains mostly declarative, but when we need to do something dynamic (like checking files), we add a script block. That’s often enough for many file checks.
Once we know whether the file is present, we can make decisions in the pipeline. For example:
Let’s suppose we only want to run the Deploy stage if a file named deploy-package.zip is found. In Declarative syntax, we might do:
pipeline {
agent any
stages {
stage('Build') {
steps {
echo "Building..."
// Build steps here
}
}
stage('Check for Package') {
steps {
script {
if (!fileExists('deploy-package.zip')) {
error "Package not found. Aborting."
}
}
}
}
stage('Deploy') {
steps {
echo "Deploying with deploy-package.zip."
// deployment steps
}
}
}
}
In Check for Package, we see if deploy-package.zip is there. If not, we call error to abort the deployment. The entire pipeline stops, preventing a deployment with missing files.
Another scenario is to mark the build as unstable if a file is missing but still allow the pipeline to continue:
script {
if (!fileExists('optional-report.txt')) {
currentBuild.result = 'UNSTABLE'
echo "optional-report.txt is missing, marking build unstable."
}
}
Now, the pipeline finishes, but Jenkins logs the result as UNSTABLE, signaling that something is not entirely correct.
We often rely on Shared Libraries in larger Jenkins setups to keep pipeline code organized. Suppose we want a standard function, checkFileExists, that can be reused across pipelines:
// vars/checkFileExists.groovy in our shared library
def call(String filePath) {
if (fileExists(filePath)) {
return true
} else {
return false
}
}
Now, in our pipeline:
@Library('my-shared-lib') _
pipeline {
agent any
stages {
stage('Shared Library Check') {
steps {
script {
if (checkFileExists('somefile.txt')) {
echo "somefile.txt found."
} else {
echo "somefile.txt missing."
}
}
}
}
}
}
This approach streamlines repeated tasks, letting us maintain the check logic in a single place. As needed, we can add logging, error handling, or custom logic to that function.
In some situations, the file we want to check might reside on a different agent or remote server. Jenkins typically runs each stage on the agent defined in the pipeline, so if the file is not in the workspace for that agent, fileExists won’t find it. We have two main strategies:
For example, we can do a basic SSH approach:
node('myAgentWithSSH') {
stage('Remote File Check') {
// We assume we have set up credentials or SSH keys for remote login
sh '''
ssh user@remoteserver "[ -f /path/to/file.txt ] && echo 'YES' || echo 'NO'"
'''
}
}
Then, parse the output, similar to our earlier shell-based check.
Here are a few tips to make file checks more effective in Jenkins:
Let’s combine multiple steps in a single pipeline snippet to see how everything fits together:
pipeline {
agent any
stages {
stage('Build') {
steps {
sh "touch build-output.jar" // a mock build
echo "Build complete."
}
}
stage('Archive Output') {
steps {
script {
if (fileExists('build-output.jar')) {
echo "Archiving build-output.jar..."
archiveArtifacts artifacts: 'build-output.jar', fingerprint: true
} else {
echo "No artifact to archive."
}
}
}
}
stage('Deployment Decision') {
steps {
script {
if (fileExists('build-output.jar')) {
echo "Proceeding with deployment..."
// deployment steps here
} else {
echo "Skipping deployment because build-output.jar is missing."
}
}
}
}
}
}
This pipeline demonstrates how a typical Jenkins flow might rely on the existence of certain files to decide which steps to run:
In this article, we discussed why checking if a file exists is a common requirement in Jenkins Pipelines, whether to confirm the presence of build artifacts, configuration files, or output logs.
We explored implementing it in Declarative and Scripted Pipelines using Groovy-based scripts and the sample scripts are available over on GitHub.