LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   bash script - for loop question (https://www.linuxquestions.org/questions/programming-9/bash-script-for-loop-question-239215/)

rignes 10-05-2004 08:02 PM

bash script - for loop question
 
This is actually my first attempt at anything useful with a bash script. This is a modified version of two functions shown in Learning the bash Shell book (oreilly). What is should do is recursively rename all the files in a directory structure given at the command prompt. I know it could probably be many times better, but it's really mostly an exercise so I can learn. Before I go on, here is the script. Keep in mind I'm trying to use purely bash and nothing else here, again for learning purposes.

Code:

#!/bin/bash

recdir ()
{
    for file in "$@"; do
        thisfile="$thisfile/$file"

        if [ -d "$thisfile" ]; then
            echo mv ${thisfile// /'\ '} ${thisfile// /_}
            echo
            mv "$thisfile" "${thisfile// /_}"
            thisfile="${thisfile// /_}"
            recdir $(command ls "$thisfile")

        else
            echo mv ${thisfile//'\ '} ${thisfile// /_}
            echo
            mv "$thisfile" "${thisfile// /_}"
            thisfile="${thisfile%/*}"
        fi
    done
}

recls ()
{
    for tryfile in "$*"; do
        if [ -d "$tryfile" ]; then
            echo mv ${tryfile// /'\ '} ${tryfile// /_}
            echo
            mv "$tryfile" "${tryfile// /_}"
            thisfile="${tryfile// /_}"
            recdir $(command ls "${tryfile// /_}")
        else
            echo mv ${tryfile// /'\ '} ${tryfile// /_}
            echo
            mv "$tryfile" "${tryfile// /_}"
        fi

    done
}

recls $1

The thing I'm seeing is that the top function recdir doesn't seem to put the full argument in the mv command, such that I end up with it splitting a filename like "filename 01.mp3" and running through the loop once for "filename" and again for "01.mp3". This is a snip of the output I get:

Quote:

mv Jeff_Lowmaster_and_Zero_Degrees_of_Freedom/01-AudioTrack Jeff_Lowmaster_and_Zero_Degrees_of_Freedom/01-AudioTrack

mv: cannot stat `Jeff_Lowmaster_and_Zero_Degrees_of_Freedom/01-AudioTrack': No such file or directory
mv Jeff_Lowmaster_and_Zero_Degrees_of_Freedom/01.mp3 Jeff_Lowmaster_and_Zero_Degrees_of_Freedom/01.mp3

mv: cannot stat `Jeff_Lowmaster_and_Zero_Degrees_of_Freedom/01.mp3': No such file or directory
mv Jeff_Lowmaster_and_Zero_Degrees_of_Freedom/02-AudioTrack Jeff_Lowmaster_and_Zero_Degrees_of_Freedom/02-AudioTrack
I've already found a perl script that is incredible called mfn that does the job, but I' really like to know what I'm doing wrong just for my knowledge.

Any constructive comments welcome and thanks.

Brian

CroMagnon 10-05-2004 10:15 PM

The problem (basically) is, when you split the parameters (for x in "$@"), they are split by spaces, and the splitting doesn't take quotes into account. If you do this at the top of your script:

Code:

IFS=`echo -e "\012\015"`
and pass -1 to ls, you might have more success.

If you're interested in alternatives, this is how I would do the whole script:
Code:

#!/bin/bash

IFS=`echo -e "\012\015"`

function recurse() {
    pushd $1
    for rdir in `ls -1A`; do
        if [ -d "${rdir}" ]; then
            mv "${rdir}" ${rdir// /_}
            recurse ${rdir// /_}
        else
            mv "${rdir}" ${rdir// /_}
        fi
    done
    popd
}

recurse $1

(Note that this script doesn't remove spaces from the directory you give as a parameter)

rignes 10-05-2004 10:32 PM

Thank you so much!

That was the perfect solution. I sort of thought IFS would be involved somehow but I didn't even think of using ls -1 in that way.

So, basically, "$@" will always, with a normal IFS variable interpret seperate arguments as divided by space if I understand you correctly?

Thanks again,

Brian

CroMagnon 10-05-2004 11:16 PM

That's right. The default IFS contains tab, newline and space, so it will split by all of these, and treat quotes as part of the 'word' they are attached to. Annoying, huh? I've been bitten by that before, expecting quotes to separate arguments... took me quite a while to figure out what was going on :)


All times are GMT -5. The time now is 02:31 PM.