Given the folder structure
/recipes/foo/.env
/recipes/bar/.env
Running the following command:
find ./recipes -type f -name '.env' -print0 | xargs -0 dirname | xargs -0 basename
Output:
foo
Trimming the command down to:
find ./recipes -type f -name '.env' -print0 | xargs -0 dirname
Output:
./recipes/bar
./recipes/foo
So for some reason piping dirname to basename causes me to lose some of the found directories.
0
There are 2 issues here:
-
The
-0
option ofxargs
indicates that the inputs are NUL-separated, not the outputs. In order to pipe the output ofxargs -0 dirname
toxargs -0 something
you must use the-z
option ofdirname
if it is supported (it is not POSIX). Else, its output is newline-separated. -
basename
does not support multiple arguments by default. If yours supports it (it is not POSIX) you can try-a
or--multiple
.find ./recipes -type f -name '.env' -print0 | xargs -0 dirname -z | xargs -0 basename -a
Else, use the
-n1
option ofxargs
:find ./recipes -type f -name '.env' -print0 | xargs -0 dirname -z | xargs -0 -n1 basename
Note: as your find
is apparently GNU find
you could skip dirname
with:
find ./recipes -type f -name '.env' -printf '%h' | xargs -0 basename -a
Note: you could also use only find
and any POSIX shell:
find ./recipes -type f -name '.env' -exec sh -c '
d="${1%/*}"; printf "%sn" "${d##*/}"' _ {} ;
Note: if, like in the example you show, the depth of the .env
files is 2 you don’t need find
, xargs
, dirname
or basename
. Your (POSIX) shell is enough (plus the printf
utility if it is not already a built-in of your shell):
for f in recipes/*; do [ -f "$f/.env" ] && printf '%sn' "${f##*/}"; done
4