One problem, two solutions (spaces in file names)

One problem, two solutions (spaces in file names)

Post by Dave » Thu, 14 Apr 2005 21:57:08



I'm working on a script to automate some mp3 downsampling.

Some of the file to be converted have spaces in the filenames which is a
problem for my script.

Either of two possible solutions but I've not managed to get my head
around either of them.

1.  A script to rename all files and directories recursively below
$basedir to remove the space.

2.  A way to pass the full quoted pathname to lame.

I've not really looked at 1 much and just can't get 2 to work.  The quotes
don't end up on the lame command line even though I've escaped them

This will obviously fail if any part of the path/filename has a space in
it.

for mp3file in `find \$cpath -name "*.mp3" | sort`
{
    lame --preset cbr "$kbps" "$mp3file" "$mp3file.conv"

Quote:}

so I tried:

for mp3file in `find \$cpath -name "*.mp3" | sort`
{
    lame --preset cbr "$kbps" "\"$mp3file\"" "\"$mp3file.conv\""

Quote:}

Is 2 failing because of lame or is the command line it produces broken?

I'm suspecting (fairly sure actually) that it's the for/find line which is
the problem.

--
Dave
I don't know what I'm doing.  That' why I'm here.

 
 
 

One problem, two solutions (spaces in file names)

Post by Andre Majore » Thu, 14 Apr 2005 22:09:37



Quote:> I'm working on a script to automate some mp3 downsampling.

> Some of the file to be converted have spaces in the filenames which is a
> problem for my script.

> Either of two possible solutions but I've not managed to get my head
> around either of them.

> 1.  A script to rename all files and directories recursively below
> $basedir to remove the space.

> 2.  A way to pass the full quoted pathname to lame.

> I've not really looked at 1 much and just can't get 2 to work.  The quotes
> don't end up on the lame command line even though I've escaped them

> This will obviously fail if any part of the path/filename has a space in
> it.

> for mp3file in `find \$cpath -name "*.mp3" | sort`
> {
>     lame --preset cbr "$kbps" "$mp3file" "$mp3file.conv"
> }

> so I tried:

> for mp3file in `find \$cpath -name "*.mp3" | sort`
> {
>     lame --preset cbr "$kbps" "\"$mp3file\"" "\"$mp3file.conv\""
> }

> Is 2 failing because of lame or is the command line it produces broken?

> I'm suspecting (fairly sure actually) that it's the for/find line which is
> the problem.

This is doomed to failure. If find returns

  a b
  c

for sees three arguments : "a", "b" and "c".

What about this ?

  find "$cpath" -name "*.mp3" -type f |
    while read filename
    do
      lame --preset cbr "$kbps" "$filename" "$filename.conv"
    done

If any of your files have newlines in their name, you'll have to use
something else (perhaps GNU find's -print0).

--
Andr Majorel <URL:http://www.teaser.fr/~amajorel/>
modesty, n.: Being comfortable that others will discover your greatness.

 
 
 

One problem, two solutions (spaces in file names)

Post by Ed Morto » Thu, 14 Apr 2005 22:45:42



> I'm working on a script to automate some mp3 downsampling.

> Some of the file to be converted have spaces in the filenames which is a
> problem for my script.

See question 16 in the FAQ(http://home.comcast.net/~j.p.h/cus-faq.html#P).

        Ed.

 
 
 

One problem, two solutions (spaces in file names)

Post by Dave » Thu, 14 Apr 2005 23:21:37



> See question 16 in the FAQ(http://home.comcast.net/~j.p.h/cus-faq.html#P).

Thank you :-)

I read the FAQ a while back and for some reason didn't think to look there
again.

--
Dave
I don't know what I'm doing.  That' why I'm here.

 
 
 

One problem, two solutions (spaces in file names)

Post by Dave » Fri, 15 Apr 2005 05:41:12



> What about this ?

>   find "$cpath" -name "*.mp3" -type f |
>     while read filename
>     do
>       lame --preset cbr "$kbps" "$filename" "$filename.conv"
>     done

> If any of your files have newlines in their name, you'll have to use
> something else (perhaps GNU find's -print0).

The vast majority of the files will be coming from Windows system so
newlines in the filenames are unlikely.

Using your example above plus the FAQ Ed pointed me to as well as more of
the FAQ, I've eventually come up with this: (currently neutered while
testing)

#!/bin/sh
# MP3Convert  - Convert all mp3 files in $basedir to $kbps
# $basedir    - "top" of the tree to convert. Below $basedir should be
#               two directories named "todo" and "done". The mp3 files
#               will be stored below "todo" and will be converted then
#               saved into an identical dir structure below "done"
# $ffile      - just the filename (might need this later)
# $destfile   - full, modified, path to the "done" dir tree

basedir=`pwd` # Change this later
#Create mp3lock for future cron job check
touch ${basedir}/mp3lock
# Get kbps factor or default to 128kbps
if [ $1 ] ; then kbps=$1 ; else ; kbps=128 ; fi
find "$basedir" -name "*.mp3" -type f |
while read filename
  do
    destfile=`echo -n "$filename" | sed 's/\/todo\//\/done\//'`
    ffile=${destfile##*/}
    fpath=${destfile%/*}
  # Check if destination dir exists, create it if not
    if [ ! -d "$fpath" ] ; then ; mkdir -p "$fpath" ; fi
    #lame --preset cbr "$kbps" "$filename" "$destfile"
    #rm "$filename"
  done
rm ${basedir}/mp3lock


the channels, eg mono, stereo, joint stereo etc such that files stored
below that will be converted with those parameters and run the whole thing
on my server with a high(ish) nice value from a cron job.

Unless anyone has a better idea.... :-)

--
Dave
I don't know what I'm doing.  That' why I'm here.

 
 
 

One problem, two solutions (spaces in file names)

Post by David Weintrau » Fri, 15 Apr 2005 05:45:39



> for mp3file in `find \$cpath -name "*.mp3" | sort`
> {
>     lame --preset cbr "$kbps" "$mp3file" "$mp3file.conv"
> }

> so I tried:

> for mp3file in `find \$cpath -name "*.mp3" | sort`
> {
>     lame --preset cbr "$kbps" "\"$mp3file\"" "\"$mp3file.conv\""
> }

A for loop has lots of problems. First of all, it is possible to
overload the command line from it. Plus, as you found out, once all of
the file names are expanded, the for loop can't find where one begins
and where one ends.

Imagine you have two files:

this is file one.mp3
this is file two.mp3

Your for loop will expand to:

for mp3file in this is file one.mp3 this is file two.mp3
do

A better way is to use a while loop:

find \$cpath -name "*.mp3" | sort | while read mp3file
do
    lame --preset cbr "$kbps" "\"$mp3file\"" "\"$mp3file.conv\""
done

This has three advantages over the for statement:
1). You won't overload your command line buffer because you are
converting 100,000 files with lame

2). The while loop executes in parallel with the find. In your for
loop, the find first has to expand before it can start

3). You don't lose the EOL character, so the read won't have problems
when your file names contains spaces.

BTW, if you also want to eliminate the spaced in the file names, you
could do something like this:

find $cpath -name "*.mp3" | sort | while read mp3file
do
    newName=`echo "$mp3file.conv" | sed 's/ /_/g'
    lame --preset cbr "$kbps" "\"$mp3file\"" "\"$newName\""
done

The sed command will convert all spaces to underscores. Probably ways
to write this a bit cleaner, but this is just off the top of my head.

 
 
 

One problem, two solutions (spaces in file names)

Post by Dave » Fri, 15 Apr 2005 08:02:12



> A for loop has lots of problems. First of all, it is possible to
> overload the command line from it. Plus, as you found out, once all of
> the file names are expanded, the for loop can't find where one begins
> and where one ends.

> Imagine you have two files:

> this is file one.mp3
> this is file two.mp3

> Your for loop will expand to:

> for mp3file in this is file one.mp3 this is file two.mp3
> do

> A better way is to use a while loop:

> find \$cpath -name "*.mp3" | sort | while read mp3file
> do
>     lame --preset cbr "$kbps" "\"$mp3file\"" "\"$mp3file.conv\""
> done

> This has three advantages over the for statement:
> 1). You won't overload your command line buffer because you are
> converting 100,000 files with lame

> 2). The while loop executes in parallel with the find. In your for
> loop, the find first has to expand before it can start

> 3). You don't lose the EOL character, so the read won't have problems
> when your file names contains spaces.

Thanks for that.  It's pretty much what Andre said (and I've
now implemented) but your explanation of why is very helpful.

Quote:

> BTW, if you also want to eliminate the spaced in the file names, you
> could do something like this:

> find $cpath -name "*.mp3" | sort | while read mp3file
> do
>     newName=`echo "$mp3file.conv" | sed 's/ /_/g'
>     lame --preset cbr "$kbps" "\"$mp3file\"" "\"$newName\""
> done

> The sed command will convert all spaces to underscores. Probably ways
> to write this a bit cleaner, but this is just off the top of my head.

Good idea.  Thanks. My own personal naming convention is to use all
lowercase except for the first letter of a word but changing space to
underline via the script is probably more generic and less likely to stuff
up existing filenames.

--
Dave
I don't know what I'm doing.  That' why I'm here.

 
 
 

1. how to extract path/file name upto the mzximum of two levels from the file name?

Dear Group,

I have a input file with the following details,

$ cat my_input.dat

/A1/b1/c1/file1
/A1/b1/file1
/A2/b1/c1/d1/file2
/A2/b1/file1
/A2/b2/file1
/A3/file1
/A3
/A4

I want to get only the first two levels. I will "unique" this ouput and
the final reault has to be,

/A1/b1
/A2/b1
/A2/b2
/A3/filename
/A3
/A4

(ie, the extracted files/path will have a maximum of two "/" s)

How would I get this done in ksh? (awk/sed anything is fine)

Thanks...

2. Minicom: [Q] How do I send '###' tones?

3. NFS problem met: How to export one directory with spaces in its name???

4. 10/100 PCI Ethernet Card Suggestions

5. Can sed replace one or more spaces with one space?

6. Repeating reboot on Sun sparc classic

7. A Solution to Four Operating Systems on One Computer with two Drives

8. Network interface...

9. tar, list of files and files with spaces in the name

10. two routers (two wans) connecting to one lan using two nics.

11. redirection of one stream to two files (eg: file and stdout)

12. tools to seperate one large text file into two small text files?

13. read FIRST SECOND < file (problems)