rename direcories recusively

Hi everone

I need to rename my directory tree. I want to define the renaming by regular expressions so i am free to what ever I like to do.

how would I rename an path like this one:

/thE/Long/patH-tO/my.litte/filE.TxT

to

/the/long/path_to/my_little/file.txt

I tried this one, but it does not realy work:

for f in `find $1 -type d`; do
echo $f
g=`expr "$f" : '\(.*\)' | tr '[A-Z]' '[a-z]'`
mv "$f" "$g"
done

thank you already :o

g=`expr "$f" : '\(.*\)' | tr '[A-Z]' '[a-z]'`

you can try replacing this line with

g=$(echo "$f" | tr [A-Z] [a-z])

still this does not work.
it needs to run recursively BUT have the perviously renamed directory name on hand.
if it does not have the "new" name it will not -find- it in the next renaming step.

any ideas?

EDIT: The code has been modified so only the child directory is modified.
Here is a sh script that will surely work:

#!/bin/sh

cat /dev/null > tmp
for f in $(find -type d); do
  echo "$f" >> tmp
done

cat /dev/null > tmp2
while read line; do
  depth=$(echo "$line" | grep -o "/" | wc -l)
  echo "$depth|$line" >> tmp2
done < tmp

sort -nr tmp2 > tmp
while read line; do
  folder=$(echo "$line" | cut -d'|' -f2)
    parent=${folder%/*}
    child=$(echo ${folder##*/} | tr [A-Z] [a-z])
  newfolder=$(echo "$parent/$child")
  echo mv "$folder" "$newfolder"
done < tmp

exit 0

It's a bit hackish but the trick is to rename deeper directories first

  • The first block of code creates a tmp file containing what find finds
  • The second block calculates the depth of the directories and writes to tmp2, for each directory, a line in the form "5|/path/to/the/direc/tory". Then the file is sorted so deeper directory are first in the file tmp
  • The third block actually rename each child directory with a pattern of choice
    Remove the echo on the last line in the third loop to rename the files

I hope you'll find this script useful!

i will try your script in a minute...

here is what I came up with...

but i can not "cd" in the for loop.(the commented line in function stepin)..any ideas?

#!/bin/bash

MYNAME=$0
FROM=$1
TO=$2

function list(){
# lists all directories on the current level
for f in `find ./ -type d`; do echo $f; done | cut -d / -f 1,2 | uniq | tail -n +2
}

function rename(){
# renames all directories on this level
# then calls "stepin" which moves on directorylevel deeper
for l in `list`
    do
    n=`echo $l | sed "s/${FROM}/${TO}/g"`
    if [ "$l" != "$n" ];then
        echo "RENAMING:        " $l " --> " $n
        mv $l $n
        echo ""
    fi
done
stepin
}

function stepin(){
# lists all directories on the current level to "cd" into them
# from here "one level deeper" rename does his job again
echo "stepping in..."
#for s in `list`; do echo "next dir is: "$s "it contains"; ls -l $s; done
for s in `list`; do echo "next dir is: "$s "it contains"; ls -l $s; cd $s; rename; done
}

echo "OLD"; list; echo "OLD_END"
rename
echo "NEW"; list; echo "NEW_END"

thank you so much :slight_smile:

I added a bit of code next to your for s in `list` loop to go back to the parent directory, so ls and cd won't fail.

#At the top of the script
CURRDIR="$PWD"

#your script....

for s in `list`; do echo "next dir is: "$s "it contains"; ls -l $s; cd $s; rename; done; 
cd ..
#Do not go back more than the working directory
if [ "$PWD" = "$CURRDIR" ]; then exit 0; fi

thank you so much ...
it took me a night and your help...but now it s working.
but onestly...i realy need you to explain to me what your lines do?

cd ..

moeves on directory backwards so from /home/user to /home
but don't I want to move forward?! at least that is waht the function "stepin" is supposed to do" so e.g. /home/user/ to /home/user/direcorty_in_home

this is twisted..sorry I dont get it....could you PELASE comment so I get out this with having learned something?!

:slight_smile: thank you

---------- Post updated at 07:03 AM ---------- Previous update was at 06:52 AM ----------

tested it ...still not working all the way
see the underscores in "level_2, level_3 and level_4" of the first directory?

I am tired...why is it not working :frowning:

this explains it all...

Yes, you're right, it renames the first parent directory, but not the others parents.
On the other hand, if you removes the cd.., you get errors like

ls: cannot access ./D144: No such file or directory
./sc.sh: line 34: cd: ./D144: No such file or directory

Sorry, I can't help you much :confused:

Did you try my script btw?

The key to this puzzle is hinted in the first post.
1) Use the "-depth" parameter to "find" such that the deepest directory is acted on first. However the moment you rename a directory your "find" results list is out of date.
2) So! I would suggest breaking out of the loop each time you rename a directory. Then repeat the full process until you get no hits.
3) It's inefficient but has a greater chance of success.

A more efficent approach is to keep the find "results" list up-to-date as you rename directories (but still working from the deepest level up). Unless there are a huge number of directories IMHO this is not really worth the effort.