views:

211

answers:

4

This command and output:

% find . -name file.xml 2> /dev/null
./a/d/file.xml
%

So this command and output:

% dirname `find . -name file.xml 2> /dev/null`
./a/d
%

So you would expect that this command:

% cd `dirname `find . -name file.xml 2> /dev/null``

Would change the current directory to ./a/d. Strangely this does not work. When I type cd ./a/d. The directory change works. However I cannot find out why the above does not work...

+8  A: 

Just noticed the backticks... use this instead:

cd $(dirname $(find . -name file.xml 2> /dev/null))

edit: with the arguments quoted (in case they contain white space):

cd "$(dirname "$(find . -name file.xml 2> /dev/null)")"
fortran
Huh, that worked. Oooo, I see it is assuming that the first two backticks are together and the second two are together.
sixtyfootersdude
quote your variable also for space in name problems.
ghostdog74
+1  A: 

Note that you can write this with one less level of backticks using find -exec:

cd `find . -name file.xml -exec dirname {} \;`

Or alternatively using GNU find's -printf action:

cd `find . -name file.xml -printf %h`
John Kugelman
Huh, didnt think about that, good point.
sixtyfootersdude
+1  A: 

you can use find's -execdir option as well

   -execdir command {} +
          Like  -exec,  but  the  specified  command  is run from the subdirectory containing the matched file, ....

so there's no need to cd

+2  A: 

Use the '$(...)' notation as in @fortran's answer. If you must use back-ticks, then you have to escape the nested ones:

cd `dirname \`find . -name file.xml 2> /dev/null\``

It gets really hairy when you want to change to the lib directory for your current version of Perl, for example.

Easy

cd $(dirname $(dirname $(which perl)))/lib

Hard

cd `dirname \`dirname \\\`which perl\\\`\``/lib

That's why the '$(...)' notation is preferrable.

Jonathan Leffler