bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: ls doesn't work in if statements in bash 4.3


From: Greg Wooledge
Subject: Re: ls doesn't work in if statements in bash 4.3
Date: Thu, 27 Mar 2014 08:01:45 -0400
User-agent: Mutt/1.4.2.3i

On Wed, Mar 26, 2014 at 09:02:02PM -0700, billycongo@gmail.com wrote:
> The original intention was to play a randomly sorted list of songs (except 
> ABBA):

See http://mywiki.wooledge.org/BashFAQ/026

I would use an approach like this:

files=()
while IFS= read -r -d '' file; do
  files+=("$file")
done < <(find . -iname '*.mp3' ! -iname '*abba*' -print0)

This would populate an array with all of the non-abba filenames.
Then you can use the techniques from FAQ 26 to select a random array
element, as many times as needed.

> for f in `ls *.mp3 | grep -v abba | sort -R`

This is wrong.  MP3 filenames ALMOST ALWAYS have spaces and other weird
rubbish in them.  This code will fail horribly on filenames with spaces
in them.

>    mplayer $f

So will this.  This will fail horribly on filenames with spaces in them
because you forgot to quote "$f".

> for f in `find . -name "*.mp3" | grep -v abba | sort -R`

This is also wrong, for the reasons already given.

See http://mywiki.wooledge.org/BashPitfalls (it's the very first one, for
a reason).


On Wed, Mar 26, 2014 at 09:15:38PM -0700, billycongo@gmail.com wrote:
> for f in `ls dog*`  doesn't work but
> 
> for f in `find dog*` does work.

They are BOTH wrong.

If you are not recursing into subdirectories, just use   for f in dog*

If you are recursing, then use find, but feed it to a while/read loop
with a process substitution.  DO NOT use a command substitution that
spits out filenames.

for f in `find ...`     # WRONG

while IFS= read -r file; do ...; done < <(find ...)               # ACCEPTABLE

while IFS= read -r -d '' file; do ...; done < <(find ... -print0) # BULLETPROOF

(The ACCEPTABLE one fails on filenames that contain newlines.  These
are rare but possible.  The BULLETPROOF one works on any filename.)

And for your immediate problem, get rid of the "always colorize ls output"
setting and replace it with the "colorize ls output if stdout is a terminal"
setting.  (Or get rid of the colorization entirely.)  I don't know how
you've got it configured, but I do know that "ls --color=always" is wrong
but "ls --color=auto" is OK.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]