LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - General (https://www.linuxquestions.org/questions/linux-general-1/)
-   -   directory renaming shell script? (https://www.linuxquestions.org/questions/linux-general-1/directory-renaming-shell-script-290223/)

Apostasy 02-14-2005 04:13 PM

directory renaming shell script?
 
In a pacticular directory of mine i have hundreds of subdirs most with ( and ) characters in the dir names... would it be possible to write a shell script to take those characters out? leaving the rest of the name intact?

example:
item-(year)-item
item-(year)-blah_blah
item_2-year-foobar

needs to be:
item-year-item
item-year-blah_blah
item_2-year-foobar

TIA :)

sigsegv 02-14-2005 05:12 PM

This should do it (there's more than one way to skin that rat):

Code:

for NAME in *; do
    NEWNAME=`echo $NAME | tr -d '(' | tr -d ')'`;
    mv $NAME $NEWNAME;
done


Apostasy 02-14-2005 06:38 PM

hey Thanks a lot! that saved me hours of manual labor lolol :D

homey 02-14-2005 06:52 PM

sigsegv,

Very nice! Do you have a good way to do sub directories also?

sigsegv 02-14-2005 08:21 PM

Quote:

Originally posted by homey
sigsegv,

Very nice! Do you have a good way to do sub directories also?

Code:

for NAME in `find ./ -type d`; do
    NEWNAME=`echo $NAME | tr -d '(' | tr -d ')'`;
    mv $NAME $NEWNAME;
done


homey 02-14-2005 08:38 PM

Quote:

for NAME in `find ./ -type d`; do
NEWNAME=`echo $NAME | tr -d '(' | tr -d ')'`;
mv $NAME $NEWNAME;
done
That fails to work for sub directories because the parent directory gets changed before the sub directory. I haven't figured this one out yet.

Here is another attempt which also fails to do sub directories....
Code:

for i in `ls -R` ; do
  j=`echo $i | tr -d '(' | tr -d ')'`
  mv $i $j
done


sigsegv 02-14-2005 10:15 PM

Quote:

Originally posted by homey
That fails to work for sub directories because the parent directory gets changed before the sub directory. I haven't figured this one out yet.
Right you are ... That's what I get for posting code without testing it :p

Code:

$ cat dirfix.sh
#!/bin/sh

for DIR in *; do
    if [ -d $DIR ]; then
        if ( echo $DIR | grep '(\|)' >> /dev/null ); then
            NEWNAME=`echo $DIR | tr -d '(' | tr -d ')'`
            mv $DIR $NEWNAME
            cd $NEWNAME
            $0
            cd -
        fi
    fi
done

The drawback to this being that you have to run the script with the full path to the script. If someone wants to work out a subroutine and the recursion, have right at it.

twantrd 02-14-2005 10:33 PM

Very nice. Thanks! You are the man.

-twantrd

homey 02-14-2005 11:40 PM

Thanks sigsegv,

That's a keeper. :)

jschiwal 02-15-2005 01:00 AM

How about:
Code:

for NAME in `find ./ -type d | tac`; do
NEWNAME=`echo $NAME | tr -d '(' | tr -d ')'`;
mv $NAME $NEWNAME;
done

The 'tac' command will reverse all of the lines so the subdirs will come first.

homey 02-15-2005 06:11 AM

Hi jschiwal,

Quote:

for NAME in `find ./ -type d | tac`; do
NEWNAME=`echo $NAME | tr -d '(' | tr -d ')'`;
mv $NAME $NEWNAME;
done
That doesn't seem to be doing the sub directories here.

sigsegv 02-15-2005 07:49 AM

tac also isn't part of my BSD system, which means it doesn't exist as far as shell scripts are concerned.

If you can't count on something to be installed in the base system, why use it for shell scripts? At that point you're better off using python/perl.

homey 02-15-2005 07:59 AM

sigsegv,

I kinda wondered what is this all about....
Code:

if ( echo $DIR | grep '(\|)' >> /dev/null )

sigsegv 02-15-2005 12:53 PM

That checks to see if the directory actually has a '(' or ')' in it's name. It's not strictly necessary, but it causes a bunch of errors to be printed if it's not there. If a directory is present and it doesn't have parentheses in it, the script will try to mv it from itself to itself, which usually results in "invalid operation" being printed on STDERR.

Make sense?
EDIT: Hrm ... After thinking about it, it also won't recurse into those directories to check for parentheses either. I'll leave that as a challenge for the others in the group.

homey 02-15-2005 02:03 PM

Thanks sigsegv,

So how would your script look if I wanted to rename something more ordinary like this to remove the word test...

/testone/testtwo/testthree
/testfour/testfive/testsix
/testseven/testeight/testnine
/muddtest/housetest/farmtest

to look like this....

/one/two/three
/four/five/six
/seven/eight/nine
/mudd/house/farm

EDIT: :( I must have had a typo as it seems to work now. ....
Code:

#!/bin/sh

for DIR in *; do
    if [ -d $DIR ]; then
        if ( echo $DIR | grep 'test' >> /dev/null ); then
            NEWNAME=`echo $DIR | sed -e 's/test//g'`
            mv $DIR $NEWNAME
            cd $NEWNAME
            $0
            cd -
        fi
    fi
done


jschiwal 02-22-2005 06:50 AM

Perhaps this might help you

> DIR='ab cd/a b c/de f/g h i'
> echo $(dirname "$DIR")/$(basename "${DIR// /_}")
ab cd/a b c/de f/g_h_i

If you install the 'tac' command, the find listing will be reversed so that the subdirectories occur first.

> find . -type d | tac
./ab cd/de fg/a b c
./ab cd/de fg
./ab cd
.

However, the last two entries may cause a problem because there are no subdirectories. But you need to rename the subdirectory before the main directory, so the answer may to write a recursive routine that transverses down the directories, or testing for a '/' charactor in $DIR after the second character.

> find ./ -type d | cut -b 3- | tac
ab cd/de fg/a b c
ab cd/de fg
ab cd

The cut command gets rid of the initial ./ which might cause problems.

However the problem I have is the spaces causing "${DIR}" to be chopped up in the for loop. Changing IFS to a newline character doesn't help, because everything gets lumps together.

jschiwal@matrix:~/test2> find ./ -type d | cut -b 3- | tac
ab cd/de fg/a b c
ab cd/de fg
ab cd

jschiwal@matrix:~/test2> IFS=\n; for dir in `/usr/bin/find ./ -type d | /usr/bin/cut -b 3- | /usr/bin/tac`; do /bin/echo - "${DIR}" -; done
- fg
ab cd -


All times are GMT -5. The time now is 06:19 PM.