Quick Unix scripting question

This doesn’t seem really up the standards of GQ, and I’m sure there is more than one approach, so IMHO seems like a good place for it.

OK, basically, I want to take a file containing a .m3u playlist, which is simply a text file with the full path for each file on each line, and copy all the songs in it to a new directory. Ideally, I could rename each song to reflect its position in the playlist; even simply renaming them to 1.mp3, 2.mp3, etc. would work for me. Actually, most files are in .ogg format, and I do need it to preserve the extension, and, of course, Unix (OK, well, Linux in this case) permits pretty much any character in a file name other than the newline character, and a good number of odd characters may be used, but file name can be guaranteed to end in either “.mp3” or “.ogg”.

There has to be some sort of simple solution to this, but Ubuntu’s been pretty smooth and I’m not used to doing anything complex from the command line these days. It also seems like the sort of thing that Perl or some other scripting language could handle easily, and I think I could figure things out enough to get that to work.

So, please, fire away with your ideas. Any help is appreciated.

No answer here, but I look forward to some solutions. I just switched to Linux recently and have been trying to learn all I can about it.

Thanks for the interesting thread - I hope there are some good responses.

Brendon Small

Here’s a completely untested Perl script which I think will do what you want.



#!/usr/bin/perl

use strict;
use warnings;

use File::Copy;

# target directory: 
my $target_dir = '/path/to/where/we/want/to/copy/them/to';

# first open the playlist file
open my $pfh, '/path/to/playlist/file.m3u' or die "Can't open playlist file: $!";

# loop over playlist line by line
while( <$pfh> ) { 
    chomp;
    my $dest = $target_dir . '/' . $_;      # new filename
    print "$_ -> $dest
";
    copy $_, $dest or die "Can't copy file $_ to $dest: $!";
}

print "done.
";


ETA: That script assumes the filenames in the .m3u file are just plain filenames without their full path attached. If you need to extract the individual filenames, try using the File::Basename module. It’s easier and works better than doing it with regexes.



{
while read fname; do
echo moving $fname
cp $fname /home/waterj2/music
done
} < musicfilelist.txt 

Obviously change the file name and directory. Renaming the files will involve some text replacement and since I’m not being paid for this I think I’ll stop here :slight_smile:

All these solutions expect that an m3u file is just a list of mp3 file names, like so:



One Toke Over The Line.mp3
Only The Lonely.mp3
Creep.mp3
Beware The Blob.mp3


If there is any more text in the file, the solutions will fail because the file needs to be parsed and the mp3 filenames extracted. Parsing can be really, really simple or really, really complex or something in-between, but we need to see the file to know what has to be done.

Small Clanger, will your solution work if there are spaces or special characters in the file names?

Assuming you’re using bash, try this . . .



typeset -i n=1
cat FILE_LIST.m3u | while read fpath; do
  ext="${fpath##*.}"
  cp "$fpath" DESTINATION/$n.$ext
  let n+=1
done


Substitute for the capitalized symbols as appropriate.

Probably not, it’s pretty brittle.

OK, tried it with spaces and it didn’t like them, bit of a shortcoming that. I guess read pulls off the first word of the name. It’s probably possible to get round that with the right sort of quotes, hmm.

To cope with spaces change the copy line to this:


cp "$fname" /home/waterj2/music

Your read is fine. It actually does pull the entire line into the variable. It’s the absence of quotes around your $fname in the copy command that breaks it when there are spaces.

. . . And that fixes that.

Showoff. But you lose points on the unnecessary use of cat. :slight_smile:



while read FILE; do
   cp "$FILE" "${i:=1}.${FILE##*.}"
   ((i++))
done < list.txt