LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   Bash script - executing a script through subdirectories (http://www.linuxquestions.org/questions/programming-9/bash-script-executing-a-script-through-subdirectories-438205/)

bubkus_jones 04-23-2006 11:47 PM

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.

jschiwal 04-24-2006 12:41 AM

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

Dark_Helmet 04-24-2006 12:52 AM

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.

bubkus_jones 04-24-2006 02:20 AM

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?

jschiwal 04-24-2006 04:55 PM

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.

Dark_Helmet 04-24-2006 05:05 PM

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.


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