0

I am trying to get all the directories that are under one directory(deployment) by using groovy(in Jenkins pipeline). To do this I used the following code snippet.

def currentDir = new File("${WORKSPACE}/deployment")
currentDir.eachFile FileType.DIRECTORIES, {
  println it.name
}

After executing this I am only receiving one directory even though there are several directories.

I tried another code snipped which gave me the entire path of the directory. But still here also I am only getting one directory path even though there are several directories.

def dir = new File("${WORKSPACE}/deployment")
dir.eachFileRecurse (FileType.DIRECTORIES) { directory ->
  println directory
}

What I actually want is the 1st solution but with all the directories. Am I doing something wrong here? Is there a setting on Jenkins pipeline to make sure that all the directories are getting visible? Please note I also allowed In Script Approval in order to execute this.

  • Try to use the [findFiles](https://www.jenkins.io/doc/pipeline/steps/pipeline-utility-steps/#findfiles-find-files-in-the-workspace) function from the Pipeline Utility Steps, it will make everything much more easy. – Noam Helmer Dec 13 '21 at 16:21
  • I actually want only the directories in a particular path. Is it possible to get only the directories from findFiles? – Janeth Fernando Dec 13 '21 at 16:49

1 Answers1

1

There are several problems with the code:

  • Groovy methods like .each*, .find* and similar ones that iterate over collections can be problematic in pipeline code.
  • The code will fail when trying to execute on a different node than "master". Groovy/Java code always runs on master, so it doesn't have direct access to WORKSPACE directory on another node. The code would try to find the directory on the master instead of the current node.

Unfortunately there is no built-in Jenkins function to iterate over directories (findFiles only iterates over files).

A good workaround is to use shell code:

// Get directory names by calling shell command
def shOutput = sh( returnStdout: true, script: 'find * -maxdepth 0 -type d' )

// Split output lines into an array
def directories = shOutput.trim().split('\r?\n')

// Make sure to use "for" instead of ".each" to work around Jenkins bugs
for( name in directories ) {
    println name
} 

By passing returnStdout: true to the sh step it will return the standard output of the command. Use trim() to strip any extraneous line breaks from the end and split() to create an array from the output lines.


Here is the PowerShell version of that code (it's mostly the same except for the first line):

// Get directory names by calling shell command
def shOutput = powershell( returnStdout: true, script: '(Get-ChildItem -Directory).Name' )

// Split output lines into an array
def directories = shOutput.trim().split('\r?\n')

// Make sure to use "for" instead of ".each" to work around Jenkins bugs
for( name in directories ) {
    println name
} 
zett42
  • 25,437
  • 3
  • 35
  • 72
  • Thank you very much for the detailed answer. I used the shell version of the code snippet. Followed `ls -l | grep -E '^d' | awk '{print $9}'` as I only wanted the directory name. – Janeth Fernando Dec 15 '21 at 05:01