Hi all,
I'm trying to write a bash command to transcode some videos into audios but am having trouble with filenames that contain spaces.
ls *flv
returns this:
Jorge Drexler - Al otro Lado del Río.flv
But in a bash for loop it doesn't work.
for f in `ls *flv`; do echo $f; done
returns this:
Jorge Drexler - Al otro Lado del Río.flv
Anybody know how to keep $f intact?
Thanks experts, Mike Wright
Around 07:29pm on Sunday, July 07, 2013 (UK time), Mike Wright scrawled:
I'm trying to write a bash command to transcode some videos into audios but am having trouble with filenames that contain spaces.
ls *flv
returns this:
Jorge Drexler - Al otro Lado del Río.flv
But in a bash for loop it doesn't work.
for f in `ls *flv`; do echo $f; done
returns this:
Jorge Drexler
Al otro Lado del Río.flv
Anybody know how to keep $f intact?
Look at the use of the IFS internal variable in bash and do something like:
IFS=$(echo -en "\n\b"); for f in `ls *flv`; do echo $f; done
Steve
07/07/2013 12:03 PM, Steve Searle wrote:
Around 07:29pm on Sunday, July 07, 2013 (UK time), Mike Wright scrawled:
I'm trying to write a bash command to transcode some videos into audios but am having trouble with filenames that contain spaces.
ls *flv
returns this:
Jorge Drexler - Al otro Lado del Río.flv
But in a bash for loop it doesn't work.
for f in `ls *flv`; do echo $f; done
returns this:
Jorge Drexler
Al otro Lado del Río.flv
Anybody know how to keep $f intact?
Look at the use of the IFS internal variable in bash and do something like:
IFS=$(echo -en "\n\b"); for f in `ls *flv`; do echo $f; done
exactly what I needed. I'd never discovered IFS before
all my youtube soundtracks can now move to google music! woohoo!!!
On 7 July 2013 20:18, Mike Wright mike.wright@mailinator.com wrote:
07/07/2013 12:03 PM, Steve Searle wrote:
Around 07:29pm on Sunday, July 07, 2013 (UK time), Mike Wright scrawled:
I'm trying to write a bash command to transcode some videos into audios but am having trouble with filenames that contain spaces.
ls *flv
returns this:
Jorge Drexler - Al otro Lado del Río.flv
But in a bash for loop it doesn't work.
for f in `ls *flv`; do echo $f; done
returns this:
Jorge Drexler
Al otro Lado del Río.flv
Anybody know how to keep $f intact?
Look at the use of the IFS internal variable in bash and do something like:
IFS=$(echo -en "\n\b"); for f in `ls *flv`; do echo $f; done
exactly what I needed. I'd never discovered IFS before
all my youtube soundtracks can now move to google music! woohoo!!!
As you've discovered, spaces in machineable filenames aren't great. However for this case you may want to consider: for F in *flv ; do echo "$F" ; done The expanded *flv items are kept as single tokens. In fact this is why "ls *flv" works to start with, it's the shell that expands the * matches (globbing), not the ls command. ls just gets the separate file names as arguments.
On 7-7-13 11:29:05 Mike Wright wrote:
I'm trying to write a bash command to transcode some videos into audios but am having trouble with filenames that contain spaces.
ls *flv
returns this:
Jorge Drexler - Al otro Lado del Río.flv
But in a bash for loop it doesn't work.
for f in `ls *flv`; do echo $f; done
returns this:
Jorge Drexler
Al otro Lado del Río.flv
Use another shell?
zsh does this:
garry@vfr$ touch foo\ bar garry@vfr$ for f in `ls foo*`;do echo $f;done foo bar garry@vfr$
In contrast, bash does:
garry@vfr$ bash %n@%m$ for f in `ls foo*`;do echo $f;done foo bar %n@%m$ exit
On 7-7-13 20:38:30 Ian Malone wrote:
As you've discovered, spaces in machineable filenames aren't great. However for this case you may want to consider: for F in *flv ; do echo "$F" ; done
This is probably the best solution offered, though.
Once, long ago--actually, on Sun, Jul 07, 2013 at 02:18:16PM CDT--Mike Wright (mike.wright@mailinator.com) said:
exactly what I needed. I'd never discovered IFS before
As you've discovered, it's quite useful to manipulate IFS. Just a suggestion, however. In scripts where you modify IFS, do something like:
IFSAVE=$IFS; ...do stuff... IFS=$IFSAVE
Depending on what you're doing to/with IFS, it can lead to confusion with other commands if it's not as expected.
Cheers, -- Dave Ihnat dihnat@dminet.com
On 07Jul2013 20:38, Ian Malone ibmalone@gmail.com wrote: | On 7 July 2013 20:18, Mike Wright mike.wright@mailinator.com wrote: | >>> I'm trying to write a bash command to transcode some videos into audios | >>> but am having trouble with filenames that contain spaces. | >>> | >>> ls *flv | >>> | >>> returns this: | >>> | >>> Jorge Drexler - Al otro Lado del Río.flv | >>> | >>> But in a bash for loop it doesn't work. | >>> | >>> for f in `ls *flv`; do echo $f; done [...] | | As you've discovered, spaces in machineable filenames aren't great. | However for this case you may want to consider: | for F in *flv ; do echo "$F" ; done | The expanded *flv items are kept as single tokens. In fact this is why | "ls *flv" works to start with, it's the shell that expands the * | matches (globbing), not the ls command. ls just gets the separate file | names as arguments.
I would like to second Ian's advice here.
Avoid mucking with IFS if you can possibly help it.
His suggestion to just go straight for:
for f in *.flv do ... work with "$f" (note the quotes) ... done
is the correct one. No mucking about needed at all.
IFS is a recipes for disaster. It has certain very limited uses, but is usually a code smell indicating you're doing things the wrong way.
The shell is actually quite good at handling filenames, even those with spaces and other punctuation, provided you take a little care.
If you are writing a script to work on these things, hacking with IFS is asking for trouble - it _may_ present apparently correct behaviour for your current set of files, but it is just moving the goalposts instead of fixing the problem. Make your script robust without IFS and it won't break on you in the future.
While we're on the topic of annoying filenames, may I point you at a few small scripts I find useful for tidying up (disclaimer: yeah, I wrote them):
frename https://bitbucket.org/cameron_simpson/css/src/tip/bin/frename Renames files using a perl expression. Same functionality as Larry Wall's rename script, slightly tweaked.
__ https://bitbucket.org/cameron_simpson/css/src/tip/bin-cs/__ Wrapper for frename, replaces spaces with underscores in filenames. With no arguments, works on *' '*, so I usually just run the command "__".
_% https://bitbucket.org/cameron_simpson/css/src/tip/bin-cs/_% Wrapper for frename, replaces %xx with its matching character and also replaces spaces with underscores in filenames. With no arguments, works on *'%'*, so I usually just run the command "_%". Very handy for URL downloads than haven't been unmunged.
lc https://bitbucket.org/cameron_simpson/css/src/tip/bin-cs/lc Lowercases filesnames and also does the %xx and spaces thing and turns "&" into "+". Really rather overkill. Handy for normalising mixed-case file collections if you don't want to preserve the case. I don't use this as much as I once did.
Anyway, I find __ and _% very handy sometimes.
Cheers,