Operating System - HP-UX
1830898 Members
3281 Online
110017 Solutions
New Discussion

One-liner challenge: renaming an entire directory tree

 
SOLVED
Go to solution

One-liner challenge: renaming an entire directory tree

Any script guru's out there ?

Goal:
Suppose you have a directory tree.
Suppose you want to replace all underscore ("_") characters in file or directory names with -let's say- the commercial 'at' ("@") character.

Pitfalls:
- Best practice would be processing each directory before descending into the directory tree.
- If you don't, when renaming a file/directory inside a directory that was renamed just before that, you may run into "file not found" errors (as I did...).

Here's something to get you started:
for i in $(find . -type f -name "*_*") ; do echo $i ; mv $i $(echo $(fname -d $i)/$(fname -b $i | sed 's/_/@/')) ; done

If I was able to sort the find list by "longest string in the top of the list", the problem of "file not found" would be bypassed. Not too happy about this script though...

Next step would be to also update the contents of files that meet certain criteria.

Hope someone has encountered this problem/challenge before...

Cheers,

Harald
4 REPLIES 4
H.Merijn Brand (procura
Honored Contributor
Solution

Re: One-liner challenge: renaming an entire directory tree

# perl -MFile::Find -MFile::Copy -e'find(sub{-d&&push@d,$File::Find::name},"tree_root");for(reverse sort@d){($n=$_)=~s/_/\@/g;move$_,$n}'

Enjoy, Have FUN!
Enjoy, Have FUN! H.Merijn

Re: One-liner challenge: renaming an entire directory tree

*drewl* I'm not into perl (yet), but I guess that's gonna have to change; can't even distinguish keywords from expressions and all...wow

Anyone got some good old c-scripting or perhaps throw in some awk or tcl ?

Thanks for taking the time to respond to my post...that was really quick !

Cheers,

Harald
Victor Fridyev
Honored Contributor

Re: One-liner challenge: renaming an entire directory tree

Try this:
find . -type f -name "*_*"|while read FNAME; do
NNM=$(basename $FNAME|sed 's/_/@/g')
mv $FNAME $(dirname $FNAME)/$NNM
done


If you need to include directories into the procedure, use the option -depth

find . -depth -name ..... etc

-depth: A position-independent term which causes descent of the directory hierarchy to be done so that all entries in a directory are acted on before the directory itself.

Regards
Entities are not to be multiplied beyond necessity - RTFM

Re: One-liner challenge: renaming an entire directory tree

I like the "while" loop over the "for i in" loop.

I like the use of variables.

I like using multiple lines over a single line.

But I definitely really like the "-depth" option for the find command.

find . -name "*_*"
./a_a
./a_a/a_a ---> file not found as dir was renamed previously ...
./a_a/a_a/a_a
./a_a/a_a/a_aa
./a_a/a_a/a_aaa
./a_a/a_a/a_aaaa
./a_a/a_aa
./a_a/a_aaa
./a_a/a_aaaa
./a_aa
./a_aaa
./a_aaaa

find . -name "*_*" -depth
./a_a/a_a/a_a
./a_a/a_a/a_aa
./a_a/a_a/a_aaa
./a_a/a_a/a_aaaa
./a_a/a_a
./a_a/a_aa
./a_a/a_aaa
./a_a/a_aaaa
./a_a
./a_aa
./a_aaa
./a_aaaa

Thank you all for your help; this has been a most enlightening scripting course.