Reputation: 4763
When using find
with $(dirname {})
, it always just outputs "." as the dirname. E.g. for:
find . -name \*.h -exec echo {} \; -exec echo $(dirname {}) \;
outputs:
./folder/folder.h
.
./folder/sub_folder/sub_folder.h
.
./test.h
.
But I would expect this:
./folder/folder.h
./folder
./folder/sub_folder/sub_folder.h
./folder/sub_folder
./test.h
.
Interestingly, creating a new shell for each find generates the correct output:
find . -name \*.h -exec sh -c 'echo $0; echo $(dirname $0);' {} \;
Upvotes: 0
Views: 691
Reputation: 26481
You might actually want to use this:
find . -name '*.h' -type f -printf "%p\n%h\n"
When you look at man find
under the printf
format section, you will notice that there are a plethora of useful flags.
Upvotes: 0
Reputation: 577
After having tested the above command through a script, it has been observed that $(dirname {})
is expanded to current directory .
'.
mkdir -p test1/test2
touch test1/test2/tests.h
find . -name \*.h -exec echo {} \; -exec echo $(dirname {}) \;
./test1/test2/tests.h
.
echo "find . -name \*.h -exec echo {} \; -exec echo $(dirname {}) \;" > checkh.sh
bash -vx checkh.sh
find . -name \*.h -exec echo {} \; -exec echo . \;
+ find . -name '*.h' -exec echo '{}' ';' -exec echo . ';'
./test1/test2/tests.h
.
.
That's why the output is always displayed as only .
current directory.
So, use your mini-script sh -c
style or Kent's solution.
A slight modification from your command will also work, i.e., put echo
inside command substitution:
find . -name \*.h -exec echo {} \; -exec $(echo dirname {}) \;
./test1/test2/tests.h
./test1/test2
Test case on the modification is as follows:
echo "find . -name \*.h -exec echo {} \; -exec $(echo dirname {}) \;" > checkh2.sh
bash -vx checkh2.sh
find . -name \*.h -exec echo {} \; -exec dirname {} \;
+ find . -name '*.h' -exec echo '{}' ';' -exec dirname '{}' ';'
./test1/test2/tests.h
./test1/test2
Upvotes: 2
Reputation: 195049
This line gives what you want:
find . -name *.h -print -exec dirname {} \;
Upvotes: 0