I\'m using find for a task and I noticed that when I do something like this:
find `pwd` -name \"file.ext\" -exec echo $(dirname {}) \\;
it will
I don't know why you're getting that, but try this:
find `pwd` -name file.ext |xargs -l1 dirname
This is because find
prints paths relative to the path it searches from. If you tried this search from /
you would get ``pwd\
for each path.
Consider the following script:
#!/bin/sh
set -x
find `pwd` -name "file.ext" -exec echo $(dirname {}) \;
set -x
shows how the expansion works and what the final command is. When run, it gives the following output:
++ pwd
++ dirname '{}'
+ find /home/kibab -name file.ext -exec echo . ';'
So, the first thing that is expanded is the pwd
. Second is $(dirname {})
. The result of those two commands is then dropped into the find command. Thus, you're telling find to -exec echo .
, so you're seeing the expected output.
When you substitute basename
for dirname
, the expansion still takes places, but the results of the expansion are different:
pwd
is expanded to the current path. In my example above, the result is /home/kibab
basename {}
is executed. The result of this command is {}
.
The find command is executed with the above substitutions in place. The final command executed looks like this:
find /home/kibab -name '*.png' -exec echo '{}' ';'
Upon inspecting the above command, you'll notice that the command now simply echo's whatever file was found.
Perhaps you want something like this?
find `pwd` -name "file.ext" -printf "%f\n"
$(dirname {})
is evaluated by the shell before being passed to find
. The result of this evaluation is .
, so you're just telling find
to execute echo .
for each file it finds.
basename {}
evaluates to {}
, so with $(basename {})
substituted for $(dirname {})
, find
will execute echo {}
for each file. This results in the full name of each file being echoed.
If you want to output the result of dirname
for each file found, you can omit the echo
:
find `pwd` -name "file.ext" -exec dirname {} \;
you do not have to call dirname() for each file found. with GNU find, you can use -printf
and its faster this way
find /path -type f -iname "*.ext" -printf "%h\n"
So the problem is that $(...) or `...` starts a new shell before make the replacement.
Consider using bash -c:
$ find . -name '*.PNG' -exec bash -c 'git mv {} $(dirname {})/$(basename {} .PNG)48.png' \;
That renames any icon on a git repo to a more standard form.
Here {} is replaced before executing anything, so the problem is gone.
For that example, TMTOWTDI, but I try to keep it simple so you can start whatever you really need to do.