Copy subdirectory of fileTree into dest vs top level folder


(Christopher Dieringer) #1

hello:

i have a fileTree. suppose it’s:

lib/
  file1.jar
  subfolder/
      ... (files) ...

i then have a copy closure:

  copy {
    from(myLibTree)
    into myDest
  }

on run, what i get is /path/to/myDest/lib/file1.jar.

what i desire is /path/to/myDest/file1.jar. note, no lib is in that path.

it’s not clear to me how to achieve this simple task. thanks!


(Janito Vaqueiro Ferreira Filho) #2

There’s probably an easier way, but the only way I know is to iterate through all files in the file tree, and add only normal files (no sub-directories):

copy {
    fileTree('lib').each { file ->
        if (file.isFile())
            from file
    }
}

(Christopher Dieringer) #3

hey @jvff, thanks. Unfortunately, the code you presented flattens the folder structure. What i’m looking to do instead is move a subdir from within a fileTree to a target.


(Janito Vaqueiro Ferreira Filho) #4

Ok, that should be easier :slight_smile:

I think you can convert it from a FileTree into a path, then add it with the desired sub-path.

copy {
    from myFileTree.asPath + '/lib'
    into myDest
}

If you need to obtain the directories in the first level of the file tree, you can transform it into a file and list its contents, adding all directories:

copy {
    myFileTree.singleFile().listFiles().each { entry ->
        if (entry.isDirectory())
            from entry
    }
    into myDest
}

I’m not sure if the myFile.singleFile() call works. If it doesn’t, you can try file(myFileTree.asPath).

Hope this helps :slight_smile:


(Lance Java) #5

from(myFileTree.files) should have the desired effect. It will ‘flatten’ the tree to a set of files


(Schalk Cronjé) #6

There are two opinionated solutions I can see:

The more simplistic solution where one just include the lib part in the from.

copy {
  from "${myLibTree}/lib", {
    include '**'
  }
  into myDest
}

A more generic solution which will handle deeper paths:

copy {
  from myLIbTree
  into myDest
  eachFile { fcd ->
    def relPath = fcd.relativePath
    if(relPath.lastName == 'lib' && fcd.isDirectory()) {
      fcd.exclude()
    } else if(relPath.parent.lastName == 'lib') {
        def segments = relPath.segments
        fcd.relativePath = new RelativePath( !fcd.isDirectory() ,(segments.take(segments.size()-2) + segments[-1]) as String[]  )
    }
  }}

The only problem with the second solution is that it leaves a dangling empty lib folder in the destination. It is something I have traditionally solved by adding a doLast { delete '/path/to/lib' } action to the task.


(Christopher Dieringer) #7

hey @Lance_Java, thank you, however flattened is not desired. ref


(Christopher Dieringer) #8

awesome! i’ll try the top solution! thx