unexpected pipeline result with find -exec

Hi All,

I probably miss something fundamental here.
I want to rename a bunch of files in subdirectories (that might contain white spaces) with names that are related.

I thought following could do the job:

find . -name *.sh -exec mv {} $(echo {} | sed -e 's/0/1/g') \;

Now to be able to see the output I generate an echo of the substitutes:

find . -name *.sh -exec echo {} $(echo {} | sed -e 's/0/1/g') \;

Interestingly echo {} equals echo {} | sed -e 's/0/1/g'.
It looks like the substitution of {} is somehow not done in the order I expected.

If I try the pipelining directly (without ${..}) it generates the right substitution (but for my purpose not usable):

find . -name *.sh -exec echo {} $(echo "2001" | sed -e 's/0/1/g') \;

Thank you very much for any idea pointing out my mistake,
best,
blued

Thanks for your interest!
To soliloquize further I think the answer is that it can't work - according to the man pages:
-exec utility [argument ...] ;
[..] If the string ``{}'' appears anywhere in the utility name or the arguments it is replaced by the pathname of the current file.
[..] Utility and arguments are not subject to the further expansion of shell patterns and constructs.

Please correct me if I am wrong,
thanks anyway,
blued.

use xargs -

find /path | xargs  <command set goes here>
#example
find /path -type f | xargs mv "{}" "{}"".old"

except I think you would be better served with a loop

find /path -type -f  -name '*.sh' | \
while read file
do
     echo "$file"  # the code you have makes no sense to me, so change this line
     # maybe you want to add 2001 to the file name, I cannot tell.
     # you are sed-ing 2001 for some reason.
     mv "$file" "$file".2001
done

You should add code to get rid of space - maybe repalce them with underlines. Unless spaces are a required feature.

Thanks for the reply. "2001" is only a place holder.

If I only wanted to add something to the filename

find . -name *.sh -exec mv {} {}.add_something \;

would work anyway.
But I wanted to process the filename; using xargs seem to suffer a similar limitation: the replacement string can't be fed into $(sed ...) or another way of processing.

find . -name "*.cpp" | xargs -I name mv name $(echo name|sed -e s/old/new/g)

In this case the string name will be fed unprocessed into sed instead of the xarg replacement.

Thanks,
best,
blued

Maybe you're looking for something like this:

find . -name "*.cpp" | sed 's/\(.*\)\(old\)\(.*\)/mv & \1new\3/' | sh

Before you run the command try this to be sure you get the right command:

find . -name "*.cpp" | sed 's/\(.*\)\(old\)\(.*\)/mv & \1new\3/'

Regards

Thanks for the reply!

As you can see it took me a while to understand what this is doing...
But it is exactly what I was looking for!
Dodgy script!

Great!
Thank you very much!
blued