I need to get all paths which has a specific file:
find apps -type f -name "project.json"
This returns something like
apps/sub/frontend-e2e/project.json
apps/sub/frontend/project.json
apps/sub/backend/project.json
But I want to exclude all paths with -e2e
in the last folder.
I tried something like
find apps -type f -name "project.json" -not \( -path "*-e2e" -prune \)
Also I need to remove apps/
and /project.json
from the beginning and the end of each path. So the result should be:
sub/frontend
sub/backend
In JS I would do
glob.sync('apps/**/project.json', {
ignore: ['apps/**/*-e2e/project.json']
}).map((path) => {
// do replacements
})
If you've got Bash 4.3 (released in 2014) or later, try this Shellcheck-clean code:
shopt -s dotglob extglob globstar nullglob
for path in apps/**/!(*-e2e)/project.json; do
p=${path#*/}
printf '%s\n' "${p%/*}"
done
shopt -s ...
enables some Bash settings that are required by the code:
dotglob
enables globs to match files and directories that begin with .
. find
shows such files by default.extglob
enables "extended globbing" (including patterns like !(*-e2e)
). See the extglob section in glob - Greg's Wiki.globstar
enables the use of **
to match paths recursively through directory trees. This option was introduced with Bash 4.0 but it is dangerous to use in versions before 4.3 because it follows symlinks.nullglob
makes globs expand to nothing when nothing matches (otherwise they expand to the glob pattern itself, which is almost never useful in programs).${path#*/}
and ${p%/*}
.printf
instead of echo
to print the outputs.Note that this code will not output anything for the path apps/project.json
. It's not clear what you would want to output in that case anyway.