brostone51 brostone51 - 2 months ago 8x
Bash Question

Collect jars into a tar without directory

I have a large project that creates a large number of jars in a path similar to

. I want to make a command to collect all the jars into one compressed tar, but without the directories. The command I have come up with so far is:
find project -name \*.jar -exec tar -rvf Collectors.tar.gz -C $(dirname {}) $(basename {}) \;
but this isn't quite working as I am intending, the directories are still there.

Does anyone have any ideas for how to resolve this issue?


Your command is quite close, but the problem is that Bash is executing $(dirname {}) and $(basename {}) before executing find; so your command expands to this:

find project -name \*.jar -exec tar -rvf Collectors.tar.gz -C . {} \;

where the -C . is a no-op and the {} just expands to the full relative directory+filename.

One general-purpose way to fix this sort of thing is to wrap up the argument to -exec in a Bash one-liner, so you invoke Bash for each individual file, and let it execute the dirname and basename at the right time:

find project -name \*.jar -exec bash -c 'tar -rvf Collectors.tar.gz -C "$(dirname "$1")" "$(basename "$1")"' '' '{}' \;

In your specific case, however, I'd point you to find's -execdir action, which is the same as -exec except that it cd's into the file's directory first. So you can simply write:

find project -name '*.jar' -execdir tar -rvf "$PWD/Collectors.tar.gz" '{}' \;

(Note that $PWD part, which is to make sure that you write to the Collectors.tar.gz in the current directory, rather than in the directory that find -execdir will cd into.)