views:

463

answers:

4

I know there are a lot of things like this around, but either they don't work recursively or they are huge.

This is what I got:

find . -name "*.so" -exec mv {} `echo {} | sed s/.so/.dylib/` \;

When I just run the find part it gives me a list of files. When I run the sed part it replaces any .so with .dylib. When I run them together they don't work.

I replaced mv with echo to see what happened:

./AI/Interfaces/C/0.1/libAIInterface.so ./AI/Interfaces/C/0.1/libAIInterface.so

Nothing is replaced at all!
What is wrong?

+1  A: 
for X in `find . -name "*.so"` 
do
 mv $X ${X/.so/.dylib}
done
Francis
If any of the directory or files names might contain spaces, quote both of mv's parameters with ".
Lachlan Roche
@Lachlan: that by itself won't help. You have to do `find ... | while read X` instead of the `for` (and do the quoting). Also, the find should probably have a `-type f`.
Dennis Williamson
+2  A: 

What is wrong is that

echo {} | sed s/.so/.dylib/
is only executed once, before the find is launched, sed is given {} on its input, which doesn't match /.so/ and is left unchanged, so your resulting command line is
find . -name "*.so" -exec mv {} {}

martinwguy
Thank you! I should have realized that... somehow... Any solution not yet mentioned?
Pepijn
A: 

He needs recursion:

#!/bin/bash

function walk_tree {
  local directory="$1"
  local i
  for i in "$directory"/*; 
  do
    if [ "$i" = . -o "$i" = .. ]; then 
        continue
    elif [ -d "$i" ]; then  
        walk_tree "$i"  
    elif [ "${i##*.}" = "so" ]; then
        echo mv $i ${i%.*}.dylib    
    else
        continue
    fi
  done

}

walk_tree "."
Tony
A: 

if you have Bash 4

#!/bin/bash

shopt -s globstar
shopt -s nullglob
for file in /path/**/*.so
do
 echo mv "$file"  "${file/%.so}.dylib"
done
ghostdog74