2

I have the following command:

$ ls -alt|head -30

which produces:

total 1891268

drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Jul 24 03:03 Beenie Man - Blessed (1995) - [MP3-V0]
drwxrwxr-- 940 ikwyl6 http         69632 Jul 24 02:54 .
drwxr-xr-x   2 ikwyl6 http          4096 Jul 21 05:38 Ratatat - Magnifique (2015) [V0]
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Jul 21 03:45 The Chemical Brothers - Born in the Echoes (2015) - CD V0
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Jul 21 03:38 Wilco - Star Wars (2015) [V0]
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Jul 19 01:45 The Jon Spencer Blues Explosion - Freedom Tower - No Wave Dance Party 2015 - 2015 (WEB - MP3 - V0)
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Jun 21 17:17 Kendrick Lamar - To Pimp A Butterfly (2015) - WEB V0
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Jun 21 17:15 Atmosphere - Sad Clown Bad Dub I (1999) [MP3-192]
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Jun 21 17:15 Joel Plaskett- The Park Avenue Sobriety Test (2015) [V0]
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Jun 21 17:11 Buena Vista Social Club - 2015 - Lost And Found [V0]
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Jun 21 17:08 Florence + The Machine - How Big, How Blue, How Beautiful (Deluxe Edition) (2015) [V0]
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Jun 21 17:08 The Prodigy - The Day Is My Enemy [2015](V0)
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Jun 21 17:07 Death Cab For Cutie - Kintsugi (2015) - WEB V0
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Jun 21 17:07 Sufjan Stevens - Carrie & Lowell (2015) [V0]
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Jun 21 17:02 Aesop Rock-Cat Food -2014-V0
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Jun 21 16:59 Hot Chip - Why Make Sense (2015) [v0]
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Jun 21 16:59 Outkast- SouthernPlayalistiCadillacMuzik [V0]
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Jun 21 16:53 Beirut - No No No (Single) (2015) - WEB V0
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Jun 21 16:52 Jedi_Mind_Tricks-The_Thief_and_the_Fallen-2015-NOiR
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Jun 21 16:46 Built To Spill - Untethered Moon (2015) [v0]
drwxr-xr-x   3 root     root          4096 Jun 12 22:18 ..
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Feb  3 03:23 Belle and Sebastian - Girls in Peacetime Want to Dance (2015) MP3 320
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Feb  3 03:19 Caribou - Our Love (2014) [v0]
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Feb  3 03:06 Bob Dylan - Shadows in the Night (2015) [V0]
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Jan  2  2015 The Smashing Pumpkins - Monuments to an Elegy - 2014 (WEB V0)
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Dec 26  2014 .sync-pi
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Dec  2  2014 AC-DC - Rock or Bust (2014) [V0]
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Dec  2  2014 The Decemberists_What a Terrible World, What a Beautiful World
drwxr-xr-x   2 ikwyl6 ikwyl6      4096 Nov 28  2014 Wu-Tang Clan - A Better Tomorrow (2014) - WEB V0

I want to be able to traverse into each of these directories and list the mp3s in them with added HTML. I know how to do this on a specific directory but doing this:

for I in ls Wilco\ -\ Star\ Wars\ \(2015\)\ \[V0\]/*; do echo "<li><a href=\"#\" data-src=\"music/$I\">$I</a></li>"; done

which gives and which I want to have as the end result for each line of mp3 (showing only 1 line for simplicity):

<li><a href="#" data-src="music/Wilco - Star Wars (2015) [V0]/01 - EKG.mp3">Wilco - Star Wars (2015) [V0]/01 - EKG.mp3</a></li>

As a start to see how I can obtain getting each directory as a variable for a nested for loop to print each mp3 in each directory, I have tried something like this:

for J in ls `ls -alt|head -30`; do
echo $J
done

but I run into roadblocks as the output takes each space in each directory name as a new line. Anyone have any ideas how I can do this? How can I get the directory name (which may have characters that may need to be escaped) as a variable for another loop?

ikwyl6
  • 851
  • 1
  • 7
  • 12

2 Answers2

1

Since your filenames contain space, use while instead of for. Use ls -At instead of ls -lat to ignore . and ..

ls -At|head -30 | while read line; do
echo "<li><a href=\"#\" data-src=\"music/${line}.mp3\">$line</a></li>"
done

Update: To loop multiple dirs

ls -d */ | while read dir; do
   ls -At ${dir} | head -30 | while read line; do
        echo "<li><a href=\"#\" data-src=\"music/${dir}${line}.mp3\">line</a></li>"
   done
done
Mahesh Kharvi
  • 389
  • 2
  • 6
  • this is what I'm looking for, but what about taking each directory and then going through each mp3 within that dir? Ie: two nested loops..? – ikwyl6 Aug 07 '15 at 02:44
  • When I change ${dir} to "$dir" it works for me. Otherwise, in the 2nd loop, the ls command receives the $dir variable as separate lines when the folder/dir has spaces in it: ls: cannot access Radiohead: No such file or directory ls: cannot access -: No such file or directory ls: cannot access 2008: No such file or directory ls: cannot access -: No such file or directory ls: cannot access Scotch: No such file or directory ls: cannot access Mist: No such file or directory ls: cannot access [V0]/: No such file or directory – ikwyl6 Aug 10 '15 at 01:45
0

As an example, let's start with these mp3 files:

$ ls */*mp3
music1/d e.mp3  music1/d.mp3  music2/a b.mp3  music2/a.mp3

There are two safe reliable ways to process file names: one is to use find and the other is to use the shell's builtin globbing. When done properly, and unlike parsing ls, both approaches will be safe for any and all file names. These two approaches are illustrated below.

Also, depending on your final usage, you may need to html-encode the file names. One way to do that is shown here. If you use the file names as part of a URL, you will want URL encoding.

Using find

Now, let's make html out of them:

$ find . -iname '*.mp3' -exec bash -c 'printf "<li><a href=\"#\" data-src=\"%s\">%s</a></li>\n" "$1" "$(basename "$1")"' none {} \;
<li><a href="#" data-src="./music2/a b.mp3">a b.mp3</a></li>
<li><a href="#" data-src="./music2/a.mp3">a.mp3</a></li>
<li><a href="#" data-src="./music1/d.mp3">d.mp3</a></li>
<li><a href="#" data-src="./music1/d e.mp3">d e.mp3</a></li>

Using bash with extglob

This finds all names of mp3 files in all subdirectories of any depth and makes them into an html list:

$ shopt -s extglob
$ for f in **/*.mp3; do printf '<li><a href="#" data-src="%s">%s</a></li>\n' "$f" "$(basename "$f")"; done
<li><a href="#" data-src="music1/d e.mp3">d e.mp3</a></li>
<li><a href="#" data-src="music1/d.mp3">d.mp3</a></li>
<li><a href="#" data-src="music2/a b.mp3">a b.mp3</a></li>
<li><a href="#" data-src="music2/a.mp3">a.mp3</a></li>

Or, written out over multiple lines:

shopt -s extglob
for f in **/*.mp3
do 
    printf '<li><a href="#" data-src="%s">%s</a></li>\n' "$f" "$(basename "$f")"
done

Parsing ls

Generally, one should not try to parse ls: with any but the simplest file names, it will fail. As an example, let's create a file whose name has a tab and a newline:

$ touch $'tab\tc\nd'

Here is what the output of ls looks like:

$ ls -At tab*
tab?c?d

Observe that ls mangled the name, replacing both tab and newline with question marks, ?.

Community
  • 1
  • 1
John1024
  • 109,961
  • 14
  • 137
  • 171