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 give you dots only for each match. When you substitute dirname
with basename
in that command you get the full pathnames. Am I screwing something up here or is this expected behavior? I'm used to basename
giving you the name of the file (in this case file.ext
) and dirname
giving you the rest of the path.
dirname is a command in Linux which is used to remove the trailing forward slahes “/” from the NAME and prints the remaining portion. If the argument NAME does not contains the forward slash “/” then it simply prints dot “.”.
dirname is a standard computer program on Unix and Unix-like operating systems. When dirname is given a pathname, it will delete any suffix beginning with the last slash ( '/' ) character and return the result. dirname is described in the Single UNIX Specification and is primarily used in shell scripts.
We can exclude directories by using the help of “path“, “prune“, “o” and “print” switches with find command. The directory “bit” will be excluded from the find search!
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"
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With