LinuxQuestions.org
Share your knowledge at the LQ Wiki.
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 04-23-2006, 11:47 PM   #1
bubkus_jones
LQ Newbie
 
Registered: Aug 2004
Distribution: Arch
Posts: 27

Rep: Reputation: 0
Bash script - executing a script through subdirectories


Ok, after checking the "simmilar threads" results, I'm still puzzled at what I should do.

I have a shell script (someone on one of the forums I go to posted it for me) which runs through all the mp3/ogg files in the current directory and changes all the file names to lower case and replaces the spaces with an underscore { from Dude - This Rocks.mp3 to dude_-_this_rocks.mp3 }.


Handy to have, but I've got my music seperated by artist and then by album (eg. ~/music/van_halen/1984). Right now I have to go into each of the directories manually and run the script. I'd like to create another script, or add to the current one, that will allow me to start in "~/music" and go through every artist and their albums and run the script.

This is the converter script, obviously enough called mp3convert
Code:
for i in *.mp3; do mv "$i" `echo $i | tr ' ' '_'`; done;
for i in *.ogg; do mv "$i" `echo $i | tr ' ' '_'`; done;

for i in *.MP3; do mv "$i" `echo $i | tr ' ' '_'`; done;

for i in *.[Mm][Pp]3; do mv "$i" `echo $i | tr '[A-Z]' '[a-z]'`; done;
for i in *.[Oo][Gg][Gg]; do mv "$i" `echo $i | tr '[A-Z]' '[a-z]'`; done;

chmod 644 *.*
So, I need a way to be able to test every file in the directory to check if it's a directory.

According to the book I"m referencing, I should use something like

Code:
if [ -d <file or directory> ]
then
cd <directory>
mp3convert;
fi
I assume I'll need to run it in a loop, too.

It's just a matter of getting the script to test the contents of the current directory.

I'll keep reading my book to see if I can figure it out. If I happen to do it before someone responds, I'll post the script here.

Thanks guys.


EDIT/UPDATE::

Ok, I can go one subdirectory deep, for example, I can run it in music/van_halen/ and it will get music/van_halen/1984 music/van_halen/balance etc. but it won't get music/van_halen/best_of_both_worlds/disc_1 or music/van_halen/best_of_both_worlds/disc_2 etc.

This is the script, so far.
Code:
#!/bin/sh


for file in *

do
        if [ -d "$file" ]; then
                cd "$file";
                ~/bin/mp3convert;
                cd ..;
                continue
        fi
done


exit 0
I just need that last little bit to get it to go into a subdirectory, then rerun the loop to check the subdirectory for any sub-subdirectories.

Last edited by bubkus_jones; 04-24-2006 at 12:30 AM.
 
Old 04-24-2006, 12:41 AM   #2
jschiwal
Guru
 
Registered: Aug 2001
Location: Fargo, ND
Distribution: SuSE AMD64
Posts: 15,733

Rep: Reputation: 654Reputation: 654Reputation: 654Reputation: 654Reputation: 654Reputation: 654
You can use the find command to return subdirectories, and use the output in a for loop. If the directories don't contain any "evil" characters this simplifies things.

for dir in $(find ./ -type d); do
....
done
 
Old 04-24-2006, 12:52 AM   #3
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 369Reputation: 369Reputation: 369Reputation: 369
You're making this far too difficult on yourself. The find command will help you tremendously. All it will take is a slight variation to your existing script.

First, the script:
Code:
#!/bin/sh

if [ -d "${1}" ] ; then
  cd "${1}"
else
  echo "Error: bad argument. Expected a valid directory name for the first argument"
  echo "Bad directory name = ${1}"
  exit 1
fi

for i in *.mp3; do mv "$i" `echo $i | tr ' ' '_'`; done;
for i in *.ogg; do mv "$i" `echo $i | tr ' ' '_'`; done;

for i in *.MP3; do mv "$i" `echo $i | tr ' ' '_'`; done;

for i in *.[Mm][Pp]3; do mv "$i" `echo $i | tr '[A-Z]' '[a-z]'`; done;
for i in *.[Oo][Gg][Gg]; do mv "$i" `echo $i | tr '[A-Z]' '[a-z]'`; done;

chmod 644 *.*
Then you run this command:
Code:
find ~/music -type d -exec ~/bin/mp3convert "${1}" \;
The change to the script just makes it so the script requires a directory name or it errors out. If the directory exists, it enters the directory and performs the renaming operations. The find command descends trough all subdirectories under (and including) ~/music. For each directory found, finds executes ~/bin/mp3convert with the first argument being the directory name it just located.
 
Old 04-24-2006, 02:20 AM   #4
bubkus_jones
LQ Newbie
 
Registered: Aug 2004
Distribution: Arch
Posts: 27

Original Poster
Rep: Reputation: 0
Hmm, I should have known that, but I didn't. Now I do. Thanks.



OK I just tried it out, but I get this
Code:
Error: bad argument. Expected a valid directory name for the 
first argument
Bad directory name =
Which leads me to believe

Code:
if [ -d "${1}" ] ; then
  cd "${1}"
is not being met/satisfied. What, exactly, is the "${1}" variable supposed to be, and how is it supposed to be set?

Last edited by bubkus_jones; 04-24-2006 at 02:31 AM.
 
Old 04-24-2006, 04:55 PM   #5
jschiwal
Guru
 
Registered: Aug 2001
Location: Fargo, ND
Distribution: SuSE AMD64
Posts: 15,733

Rep: Reputation: 654Reputation: 654Reputation: 654Reputation: 654Reputation: 654Reputation: 654
There is an alternate way of renaming files using filename expansion of bash variables.

mv "$i" "${i//[ \!,:]/_}"
Between the square brackets, place the set of characters to replace with an underscore.

The exclamation point is especially nasty in filenames and commands. In my example, it needs to be escaped with a backslash even though it is in double quotes. Otherwise it will try executing a line in your bash history buffer.
 
Old 04-24-2006, 05:05 PM   #6
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 369Reputation: 369Reputation: 369Reputation: 369
The ${1} reference expands to the first argument on the command line. That is to say, if you entered this:
Code:
~/bin/mp3convert ~/some_dir/
The ${1} evaluates to "~/some_dir/"

I made a mistake in my find command earlier. The ${1} used in the command line was a mistake. It should be {}. Just had a mental "oops" while thinking about referencing arguments in a shell script earlier. Here's the correct command:
Code:
find ~/music -type d -exec ~/bin/mp3convert "{}" \;
If that still doesn't do what you want, then you may need to pursue jschwial's suggestions.
 
  


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
Using Bash, Find script files in a directory or subdirectories within... ray5_83 Programming 4 10-10-2008 07:42 PM
executing a script in multiple subdirectories jerryfreak Linux - Newbie 1 04-19-2005 08:34 PM
send automatic input to a script called by another script in bash programming jorgecab Programming 2 04-01-2004 12:20 AM
bash script prob: how can i tell the script that a 'dd' has finished? Frustin Linux - General 2 04-02-2003 05:34 AM
Script For Moving Files In Subdirectories darkmage Linux - General 3 12-17-2002 06:34 PM


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

Main Menu
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