Instead of relying on external commands, where you lose the information about the current directory, you can use find
's -execdir
option to have it execute commands in the directory a file was found in.
find . -name oldfile.txt -execdir mv -- {} newfile.txt \;
This is actually a more secure version of -exec
that is preferred in most situations. The only drawback is that it's not specified by POSIX, so you won't find it in all find
variants – but at least in GNU find
and BSD find
you can.
If you want to be extra safe, you should call mv
like mv -- source target
so that a file starting with a dash isn't incorrectly interpreted as an argument to mv
.
If for some reason you don't want to use -execdir
or have other complicated things to do, or just want to learn a little about Bash, here's how to get the folder and move the file based on that:
find . -name oldfile.txt -exec bash -c 'mv -- "${0}" "$(dirname $0)"/newfile.txt' {} \;
Here, {}
passes the full path to bash
as $0
. We get its directory name through command substitution ($(…)
) and then append the new name. Both the original argument and the directory name have to be double quoted to prevent whitespace from breaking the command – otherwise mv
would think you're trying to move two files called foo
and bar
when the file is actually called foo bar
, for example.
This worked! Excellent solution. The third paramater of
mv
is the directory? I've never seen mv have a third param. I looked at the manual but it doesn't seem clear. – Chris Bier – 2013-05-17T19:28:37.943No, it has nothing to do with
mv
. The\;
is part of the-exec
/-execdir
option – see thefind
manual I linked you to. You always have to include it in order to havefind
recognize the end of the command specified inexec
. – slhck – 2013-05-17T19:29:51.523Ah I see!
Both of these constructions need to be escaped (with a ‘\’) or quoted to protect them from expansion by the shell.
That means that{}
should be escaped as well. – Chris Bier – 2013-05-17T19:31:47.283You don't really have to escape or quote
{}
, it also works without that in most shells orfind
versions. Quoting{}
is only necessary when it would be interpreted otherwise by the shell, which usually isn't the case. I think @DanielBeck recently had a problem with thefish
shell and that – but I'm not entirely sure iffish
was the whole cause of the issue. – slhck – 2013-05-17T19:37:25.023Added another example of how to achieve what you need, albeit a little more complicated than it needs to be. – slhck – 2013-05-17T19:44:57.400