# Terminal Terminology Help, Please



## shatfield1529 (Aug 1, 2002)

The many MP3s on my HD are organized in folders using the following scheme by iTunes:

iTunes\ Music/artist/album/track

What I want to do is, using the 'printf' command, create a file 'albumlist' which, obviously enough, is a list of all the albums on my HD. 

What I planned on doing was just use 'printf' and have it print 'iTunes\ Music/*/*' to 'albumlist' with the format 'Artist - Album\n'. Compilations aren't a problem, as the folder scheme would make it appear as 'Compilation - Album'.

The hard part is, tracks without a designated album are put in a folder 'Unknown Album'.

Being relatively inexperienced with UNIX, how would I use the 'printf' command to format my output like this, and also prevent results including the string 'Unknown Album' from appearing in 'albumlist'?

Thanks in advance.

P.S. - If it's relevant, my shell type is tcsh.


----------



## lethe (Aug 1, 2002)

i m not sure i understand what you need to do....


how about something like this:  


```
for x in `ls iTunes\ Music/`
do
   for y in `ls $x`
      do
           echo "$x - $y"
      done
done
```

this is in bash, not tcsh.  i think it should work in sh too.  don t program in tcsh.  x will become each artist, and y will become each album under that artist.


----------



## shatfield1529 (Aug 2, 2002)

The general direction of what I was thinking of was something to the effect of (in English):

For every album of every artist, print "Artist - Album" into a new file 'albumlist'. If the name of the Album is "Unknown Album", though, do not print "Artist - Album" into 'albumlist'.

Sorry if this muddles it up more.


----------



## lethe (Aug 2, 2002)

well the thing i posted above will do something like that.  except that it doesn t check for 'Unkown Artist' or anything like that.  you would just have to redirect it.

try something like this:

1.  save that text to a file, using cat, or nano or pico or emacs or whatever.  you can even use TextEdit.app, as long as you make sure to save as a textonly file.  lets assume you saved it as mp3albums

2.  open terminal, and cd to the directory where you saved the text file above.  

3.  type this 'chmod 755 mp3albums'  to make the file executable

4.  run the file like this:  ./mp3album  .   if the output looks like what you want, then type './mp3albums > albumlist'

then you are done.  if the output is not like you want it, then come here and tell us what it doesn t do.  if it is close, then we can fix it.  if it is nothing at all like what you need to do, then we will have to try a new approach.

OH yeah, you should add this line to the top of the file before you run it:


```
#!/bin/sh
```

just stick that line as the first line of the script, to make sure the computer knows its a bourne shell script


----------



## shatfield1529 (Aug 2, 2002)

Okay, I tried it out, but the output is a little funky.

Here's an example:



> Aerosmith - Aerosmith's
> Aerosmith - Greatest
> Aerosmith - Hits
> ...
> ...



With Artists and Albums which consist of single words, it works. Otherwise, it echoes each separate word. As you can see, this causes problems with the ls output.

I made doubly sure to use the right quotes and to put in the #!/bin/sh at the top, so is it just a matter of adding a quote or other character somewhere? Because it seems to work fine otherwise.


----------



## lethe (Aug 2, 2002)

oh yeah.  shell scripts have a real problem with files with spaces in their names.  let me think about this.


----------



## lethe (Aug 2, 2002)

OK, try this:


```
#!/bin/sh

for x in `ls iTunes\ Music/ | sed 's/ /_/g'`
do
	for y in `ls $x | sed 's/ /_/g'`
		do
			echo "$x - $y"
		done
done
```

if you save that to a file as before, and make it executable, i think it should work as before, except it will replace the spaces with underscores.  you can change it back by running the command like this:


```
%./mp3albums | sed 's/_/ /g'
```

and as before, if you want to put the output into a file:

```
%./mp3albums | sed 's/_/ /g' > albumlist
```

i haven t tried this script out or anything, so let me know how it works.


----------



## shatfield1529 (Aug 2, 2002)

With the new script, output looks like this:



> 2001 - Unknown Album
> 2Pac - Makaveli
> 2Pac - Me Against The World
> ls: 3_Doors_Down: No such file or directory
> ...



The script has no problem with albums, but when it replaces the spaces in the artist folder name with underscores and then tries to look *in* the folder with underscores in the name, there's no folder to be found.


----------



## lethe (Aug 2, 2002)

OK OK, we re getting closer though...


```
#!/bin/sh

for x in `ls iTunes\ Music/ | sed 's/ /\\\ /g'`
do
	for y in `ls $x | sed 's/ /\\\ /g'`
		do
			echo "$x - $y"
		done
done
```

i m not sure whether this will work.  here i replace the spaces with escaped spaces instead.  i think it won t work.  give it a try


----------



## lethe (Aug 2, 2002)

maybe this:


```
#!/bin/sh

for x in `ls iTunes\ Music/ | sed 's/ /_/g'`
do
	z=`echo $x | sed 's/_/\\\ /g'`
	for y in `ls $z | sed 's/ /_/g'`
		do
			echo "`echo $x | sed 's/_/ /g'` - `echo $y | sed 's/_/ /g'`"
		done
done
```

i hope you don t have any files or folders with underscores in the names, or it will screw everything up.  i changed the echo line this time to take out the underscores in the output.  lots of quotations and backquotes, so i hope there is no syntax error.


----------



## shatfield1529 (Aug 2, 2002)

Your most recent script solved the album name issue, but the artist name issue is still there. Here's how it looks:



> Aerosmith - Aerosmith's Greatest Hits
> ...
> ls: Williams,\: No such file or directory
> ls: Robin: No such file or directory
> ...



I also solved my peeve with the 'Unknown Album' issue, by adding another sed to the 'echo $y' block;


```
#!/bin/sh

for x in `ls iTunes\ Music | sed 's/ /_/g'`
do
        z=`echo $x | sed 's/_/\\\ /g'`
        for y in `ls $z  | sed 's/ /_/g'`
                do
                        echo "`echo $x | sed 's/_/ /g'` - `echo $y | sed 's/_/ /g' | sed 's/Unknown Album/Misc. Tracks/g'`
                done
done
```

I fiddled around with the various 'sed' blocks to get $x to output right, but nothing really turned up.


----------



## shatfield1529 (Aug 2, 2002)

ls still won't deal correctly with instances of 'x' with spaces in it. The script will start off with saying:


> ls: Band: No such file or directory
> ls: of: No such file or directory
> ls: Blues: No such file or directory
> ls: and: No such file or directory
> ...



It will end up echoing instances of 'x' with spaces in it correctly by themselves, it just won't look inside those folders and echo the album folders too.

Example:


> Aerosmith: <-- Artist (no spaces)
> Aerosmith's Greatest Hits <-- Albums belonging to Artist
> Big Ones
> Nine Lives
> ...



I think we're getting close; it's just a matter of switching some puncuation maybe.


----------



## shatfield1529 (Aug 2, 2002)

Hm... Where did testuser's post go?

Anyway, his script (which I refered to in my last post) looked like this:


```
#!/bin/sh
for x in "`ls iTunes\ Music/`"
do
        for y in "`ls $x`"
                do
                        echo "$x - $y"
                done
done
```


----------



## lethe (Aug 3, 2002)

to be perfectly honest, shatfield, i was sort of faking my way through this answer, waiting for someone more experienced in scripting (Read: testuser) came along and set us straight.  i m anxious to see if his script works for you, and i started thinking that i should make a script like this for myself.  my mp3s are in a state of disarray that some good scripting could do wonders for.


----------



## shatfield1529 (Aug 3, 2002)

You'll have to forgive me; this script issue has been gnawing at my mind, and I may seem really eager. Maybe it's not a problem. 

The problem with this new script is that now it splits up the album names, so that it looks like this:



> Beck - Mellow
> Beck - Gold
> Beck - Unknown
> Beck - Album
> ...


----------



## sao (Aug 3, 2002)

shatfield1529,

 The following have helped me in the past to deal with iTunes music library. Is a great perl script made by *pmccann* and dropped at the MacOS X Hints forum:

 It will give you a summary information about the music library in different forms, like the following:

 A little bit from every section: 

------------------------ 
Artist: Africando 
Albums: , 12 Hits, Baloba, Gombo Salsa 
------------------------- 

------------------------- 
Artist: Afro Cuban All Stars 
Albums: A Toda Cuba Le Gusta, Distinto, diferente 

==============================x 

Artist: Ian Sheffield 
------------------------- 
Album: Ian Sheffield's Greatest Hits 
Contains the tracks 
------------------------- 
Muppets - Hugga Wugga 

Artist: Ibrahim Ferrer 
------------------------- 
Album: Buena Vista Social Club 
Contains the tracks 
------------------------- 
Cienfuegos Tiene Su Guaguanc? 

==============================x 

Album: SUS PRIMEROS EXITOS 
Contains the tracks 
------------------------- 
La Atardecida 
La Nostalgiosa 
Qu? Bonita Va 
Coplas Del Valle 
No Te Puedo Olvidar 

==============================x 

Artist: Royal College of Music Chamber 
------------------------- 
Album: Carols For Christmas - Vol 2 
Contains the tracks 
------------------------- 
Good King Wenceslas 

==============================x 

Artist: Vienna Boys Choir 
------------------------- 
Album: Season's Greetings 
Total playing time: 3 minutes, 42 seconds 

Artist: Walt Disney Records 
------------------------- 
Album: Classic Disney Volume II 
Total playing time: 2 minutes, 42 seconds 

==============================x 




*Continue ....in the next post*


 Cheers...


----------



## shatfield1529 (Aug 3, 2002)

Sao,

Thanks. Do you have a link?


----------



## sao (Aug 3, 2002)

*Continue...*


 "In iTunes go to "Advanced/Export Song List..." and get yourself a text file listing of all the music that you have imported. If you're library isn't too stupendously large you might like to try exporting the whole thing. 

Yeah, give it a go! iTunes makes a text file with the following format: all items are tab separated, and I've only shown the line of headers and a single song. The line breaks are "classic Mac", which we'll work around in the script below."


```
#!/usr/bin/perl -w 
use strict; 
my $export_file = '/Users/pmccann/Desktop/Library.export'; 
# Change this to where you save your iTunes export file 

$/="\015"; 
# itunes exports with "classic" mac line endings, so we need to 
# let perl know this. $/ is the "chunk separator", which is a unix 
# end of line character by default (ie "\012"). 

my %song_info; #hash to hold all the info of interest 
open IN,$export_file or die "infile error: $!"; 
my @headings = split "\t",<IN>; # headings are in the first line of the file 
# We don't actually do anything with them here, but you might want to! 
while (<IN>){ 
my ($artist,$album,$song,$time,$track)=(split "\t",$_)[1,2,0,5,6]; 
# Just picking out the 5 chunks of information that interest us here! 
$song_info{$artist}{$album}{$song}{'time'}=$time||0; 
$song_info{$artist}{$album}{$song}{'track'}=$track||0; 
} 

# Now try to get something useful out of the other end!! 
# First let's get a simple list of the artists 

my @artists = sort keys %song_info; # the keys of the hash are the artists 
print "Artists: ", join(", ", @artists),"\n\n"; 

# How about a list of the albums by each artist? 

foreach my $artist_item (@artists){ 
print "-"x25,"\n"; # Just as a separator 
my @albums = sort keys %{$song_info{$artist_item}}; 
# $song_info{$artist_item} is a hash reference, so we're just asking for 
# the keys of the hash that this reference "refers to/points to". 
print "Artist: $artist_item\n","Albums: ",join(", ",@albums),"\n","-"x25,"\n\n"; 
} 

# And the songs for each album by each artist? 
foreach my $artist_item (@artists){ 
my @albums = sort keys %{$song_info{$artist_item}}; # Just as above 
print "Artist: $artist_item\n"; 
print "-"x25,"\n"; # Just as a separator 
foreach my $album_item (@albums){ 
print "Album: $album_item\nContains the tracks\n","-"x25,"\n"; 
my @songs = sort { $song_info{$artist_item}{$album_item}{$a}{'track'} <=> $song_info{$artist_item}{$album_item}{$b}{'track'} } keys %{$song_info{$artist_item}{$album_item}}; #Yech! See below 
print join("\n",@songs),"\n\n"; 
} 
} 

# Finally, how about using the $time information for each song to produce a 
# summary of the total playing time of each "album"? 

foreach my $artist_item (@artists){ 
my @albums = sort keys %{$song_info{$artist_item}}; 
print "Artist: $artist_item\n"; 
print "-"x25,"\n"; # Just a separator 
foreach my $album_item (@albums){ 
my $total_time; 
print "Album: $album_item\n"; 
my @song_list = keys %{$song_info{$artist_item}{$album_item}}; 
foreach my $song_item (@song_list){ 
$total_time += $song_info{$artist_item}{$album_item}{$song_item}{'time'}; 
} 
printf "Total playing time: %d minutes, %d seconds\n\n",$total_time/60,$total_time%60; 
} 
}
```





 Give it a try, I found it very useful.


 Cheers...


----------



## sao (Aug 3, 2002)

JeJe  

 The comments are from *pmccann* telling us mere mortals how the script is supposed to work. Thanks to them I made some sense of the commands.


 Hope it helps somebody, it really helped me.


 Cheers...


----------



## shatfield1529 (Aug 3, 2002)

Yay! It works!

Thank you testuser!

It's been a learning experience for all of us.



The perl script sao provided wouldn't work with iTunes 3, since 3 added the Composer, My Rating, etc. fields. It wasn't until after I tried it that I figured that out. Thanks for listing it, though!


----------



## sao (Aug 3, 2002)

shatfield1529,

 Sorry about that, I forgot about iTunes3.

 Will beg for an update from pmccann.


 Cheers...


----------



## sao (Aug 11, 2002)

shatfield1529,


 I found out that the 'pmccann' script also works well if you just change the output file of iTunes3 to the name 'Library.export' as it is called originally in the script.

 And it also works with the original chunks of info numbers:

 my ($artist,$album,$song,$time,$track)=(split "\t",$_)[1,2,0,5,6];

 as well as with the numbers that testuser showed us:

 my ($artist,$album,$song,$time,$track)=(split "\t",$_)[1,3,0,6,9];


 Cheers...


----------

