LinuxQuestions.org
Support LQ: Use code LQ3 and save $3 on Domain Registration
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices



Reply
 
Search this Thread
Old 10-05-2004, 09:02 PM   #1
rignes
Member
 
Registered: Mar 2003
Location: USA
Distribution: Slackware-current
Posts: 155

Rep: Reputation: 30
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
 
Old 10-05-2004, 11:15 PM   #2
CroMagnon
Member
 
Registered: Sep 2004
Location: New Zealand
Distribution: Debian
Posts: 900

Rep: Reputation: 33
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)
 
Old 10-05-2004, 11:32 PM   #3
rignes
Member
 
Registered: Mar 2003
Location: USA
Distribution: Slackware-current
Posts: 155

Original Poster
Rep: Reputation: 30
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
 
Old 10-06-2004, 12:16 AM   #4
CroMagnon
Member
 
Registered: Sep 2004
Location: New Zealand
Distribution: Debian
Posts: 900

Rep: Reputation: 33
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
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
bash script loop bong.mau Programming 6 09-14-2005 08:38 PM
Bash Script and Loop error handling Kedelfor Programming 5 05-22-2005 03:22 PM
bash script for loop drisay Programming 5 12-25-2004 01:32 AM
Bash script question deiussum Programming 6 08-14-2004 12:43 PM
while loop ending prematurely in a bash script meat-head Programming 7 05-08-2004 02:46 AM


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

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration