views:

757

answers:

5

Hi all,

I have a lit of files (which I get from find bla -name "*.so") such as:

/bla/a1.so /bla/a2.so /bla/blo/a3.so /bla/blo/a4.so /bla/blo/bli/a5.so

and I want to rename them such as it becomes:

/bla/liba1.so /bla/liba2.so /bla/blo/liba3.so /bla/blo/liba4.so /bla/blo/bli/liba5.so

... i.e. add the prefix 'lib' to the basename

any idea on how to do that in bash ?

cheers Dave

+4  A: 

Something along the lines of:

for a in /bla/a1.so /bla/a2.so /bla/blo/a4.so
do
  dn=$(dirname $a)
  fn=$(basename $a)
  mv "$a" "${dn}/lib${fn}"
done

should do it. You might want to add code to read the list of filenames from a file, rather than listing them verbatim in the script, of course.

unwind
Thanks to (I guess) Aaron for adding quotes, that's a good point.
unwind
yes of course, I forgot about dirname so I couldn't see how to split path easily... thanks ! altough the last line should: mv $a $dn/lib$fn otherwise, bash will think of dn and fn as shell commands
DavidM
+1 for using `$()` instead of backticks.
Dennis Williamson
+1  A: 

Try mmv:

cd /bla/
mmv "*.so" "lib#1.so"

(mmv "*" "lib#1" would also work but it's less safe).

If you don't have mmv installed, get it.

Aaron Digulla
mmv sounds powerful ! thanks for the info
DavidM
A: 

basename and dirname are your friends :)

You want something like this (excuse my bash syntax - it's a little rusty):

for FILE in `find bla -name *.so` do
    DIR=`dirname $FILE`;
    FILENAME=`basename $FILE`;
    mv $FILE ${DIR}/lib${FILENAME};
done

Beaten to the punch!

nfm
+2  A: 
find . -name "*.so" -printf "mv '%h/%f' '%h/lib%f'\n" | sh

The code will rename files in current directory and subdirectories to append "lib" in front of .so filenames.

No looping needed, as find already does its recursive work to list the files. The code builds the "mv" commands one by one and executes them. To see the "mv" commands without executing them, simply remove the piping to shell part "| sh".

find's printf command understands many variables which makes it pretty scalable. I only needed to use two here:

  • %h: directory
  • %f: filename

Tested and works.

Wadih M.
You might want to add an appropriate `mindepth` and `maxdepth` to the find command and protect the file and directory names with quotes in case they [shudder] have spaces in them. `find . -mindepth 2 -maxdepth 2 -name "*.so" -printf "mv '%h/%f' '%h/lib%f'\n" | sh`
Dennis Williamson
I agree for the quotes, i've updated my code in consequence.
Wadih M.
A: 

Note I've commented out the mv command to prevent any accidental mayhem

for f in *
do
    dir=`dirname "$f"`
    fname=`basename "$f"`
    new="$dir/lib$fname"
    echo "new name is $new"
    # only uncomment this if you know what you are doing
    # mv "$f" "$new" 
done
anon