zsh-users
 help / color / mirror / code / Atom feed
* somehow offtopic: looping filenames
@ 2012-02-20 18:16 meino.cramer
  2012-02-20 18:38 ` Frank Terbeck
  2012-02-20 19:05 ` Bart Schaefer
  0 siblings, 2 replies; 6+ messages in thread
From: meino.cramer @ 2012-02-20 18:16 UTC (permalink / raw)
  To: zsh-users

Hi,

how can I do this in a most compact, direct, and zsh like way:

I habe a loop like this:

for fn *
do
    flac $fn
done

Unfortunately, some file have 'illegal' filenames like

    20120220-_-19db.wav
or
    20120220 sensor10 up.wav


which parts flac sees as unknown commmand options or as
two file and the loop fails.

How do I have to modifiy the loop to make it immune against
such filenames ?

Thank you very much in advance for any help!

Best regards
mcc


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: somehow offtopic: looping filenames
  2012-02-20 18:16 somehow offtopic: looping filenames meino.cramer
@ 2012-02-20 18:38 ` Frank Terbeck
  2012-02-20 19:05 ` Bart Schaefer
  1 sibling, 0 replies; 6+ messages in thread
From: Frank Terbeck @ 2012-02-20 18:38 UTC (permalink / raw)
  To: zsh-users

meino.cramer@gmx.de wrote:
> I habe a loop like this:
>
> for fn *
> do
>     flac $fn
> done
>
> Unfortunately, some file have 'illegal' filenames like
>
>     20120220-_-19db.wav
> or
>     20120220 sensor10 up.wav
>
>
> which parts flac sees as unknown commmand options or as
> two file and the loop fails.

So, you're setting `sh_word_split'? Or are you using another shell?

This should work in every shell:

  for i in ./*; do
      flac "$i"
  done

The ./ makes sure the file name cannot start in a dash, which many
applications would otherwise take as an option name. The "$i" makes sure
the shell sees the variable contents as one word. Zsh does that with
unquoted parameters by default. You'll have to set the `sh_word_split'
option to get a more bourne-shell-like behaviour.

Regards, Frank

-- 
In protocol design, perfection has been reached not when there is
nothing left to add, but when there is nothing left to take away.
                                                  -- RFC 1925


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: somehow offtopic: looping filenames
  2012-02-20 18:16 somehow offtopic: looping filenames meino.cramer
  2012-02-20 18:38 ` Frank Terbeck
@ 2012-02-20 19:05 ` Bart Schaefer
  2012-02-21 12:35   ` Stephen Blott
  1 sibling, 1 reply; 6+ messages in thread
From: Bart Schaefer @ 2012-02-20 19:05 UTC (permalink / raw)
  To: zsh-users

On Feb 20,  7:16pm, meino.cramer@gmx.de wrote:
}
} I habe a loop like this:
} 
} for fn *
} do
}     flac $fn
} done
} 
} Unfortunately, some file have 'illegal' filenames
} which parts flac sees as unknown commmand options or as
} two file and the loop fails.

Try this:

    for fn *
    do
	flac $fn:a
    done

The :a modifier expands $fn into a full path including removing any
mentions of "./" and "../".  Think of it as a clean "$PWD/$fn".

If you don't have a recent-enough zsh for :a to be supported or it is
for some reason important to avoid the full path, try

	flac ${${fn:h}-.}/${fn:t}

If that's still confusing it because e.g. you have SH_WORD_SPLIT turned
on, wrap the expression in double quotes.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: somehow offtopic: looping filenames
  2012-02-20 19:05 ` Bart Schaefer
@ 2012-02-21 12:35   ` Stephen Blott
  2012-02-21 13:35     ` Frank Terbeck
  0 siblings, 1 reply; 6+ messages in thread
From: Stephen Blott @ 2012-02-21 12:35 UTC (permalink / raw)
  To: zsh-users

On Mon, Feb 20, 2012 at 11:05:30AM -0800, Bart Schaefer wrote:
> On Feb 20,  7:16pm, meino.cramer@gmx.de wrote:
> }
> } I habe a loop like this:
> } 
> } for fn *
> } do
> }     flac $fn
> } done
> } 
> } Unfortunately, some file have 'illegal' filenames
> } which parts flac sees as unknown commmand options or as
> } two file and the loop fails.
> 
> Try this:
> 
>     for fn *
>     do
> 	flac $fn:a
>     done
> 
> The :a modifier expands $fn into a full path including removing any
> mentions of "./" and "../".  Think of it as a clean "$PWD/$fn".
> 
> If you don't have a recent-enough zsh for :a to be supported or it is
> for some reason important to avoid the full path, try
> 
> 	flac ${${fn:h}-.}/${fn:t}
> 
> If that's still confusing it because e.g. you have SH_WORD_SPLIT turned
> on, wrap the expression in double quotes.
> 
---end quoted text---

Or:

ls | tr '\n' '\0' | xargs -0 -n 1 flac --

If you're using Gnu xargs then you might need the -r/--no-run-if-empty flag
too.

Steve


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: somehow offtopic: looping filenames
  2012-02-21 12:35   ` Stephen Blott
@ 2012-02-21 13:35     ` Frank Terbeck
  2012-02-22 23:41       ` Mark van Dijk
  0 siblings, 1 reply; 6+ messages in thread
From: Frank Terbeck @ 2012-02-21 13:35 UTC (permalink / raw)
  To: zsh-users

Stephen Blott wrote:
[...]
> ls | tr '\n' '\0' | xargs -0 -n 1 flac --

This is a pet peeve of mine, so I need to chime in...

Using ls for generating file lists is always wrong. And always, there is
a more robust way of dealing with the problem at hand using either shell
globing or `find(1)'. (I used to have two "almost"s in that paragraph,
but leaving them in would really overstate the relevance of possible
situations¹.)

There is nothing about this, that would improve the behaviour of a
simple for loop like

  for i in *; flac -- $i

(That's `short_loops' syntax, which is on by default in zsh. And it
relies on `sh_word_split' being unset, which is also the default
behaviour in zsh.)

Worse, it's *less* robust, because it's treating newline characters
specially, although they are perfectly legal characters in a file name
(albeit not very common ones). Also, if the user has an alias in place,
like say,

  alias ls='ls -F'

...that is not going to work either, because that will cause ls to
append a / to directory names, a * to executable files and so on.


I know there are HOWTOs and tutorials online, that advocate constructs
like that. And even worse ones, like "for i in `ls`; do...". But that
doesn't make them good examples of shell programming.


I don't mean to offend with this reply. And I hope that my point is
making sense to you. I've written about this in the past² (but it's in
German) and so has the guy who maintains the FAQ for #bash (the IRC
channel for GNU bash on freenode)³. Refer that that for more details on
parsing the output from `ls'.


Regards, Frank

¹ There was one time, when someone asked me: Okay so "for i in `ls`" is
  bad, but what about when I want the generated list to be sorted by
  some criteria (like by modification time instead of the usual
  alphabetic order). And that's indeed not that easy with POSIX shell.
  In zsh, however, there are glob qualifiers like (O.) and (o.)
  (where`.' is a character that specifies a property to sort by), which
  allow the user to sort the result of a glob to his/her requirements.
  So that point is moot as well, if we're talking about zsh.

² <http://bewatermyfriend.org/posts/2007/02-08.12-18-45-rants.html>
³ <http://mywiki.wooledge.org/ParsingLs>


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: somehow offtopic: looping filenames
  2012-02-21 13:35     ` Frank Terbeck
@ 2012-02-22 23:41       ` Mark van Dijk
  0 siblings, 0 replies; 6+ messages in thread
From: Mark van Dijk @ 2012-02-22 23:41 UTC (permalink / raw)
  To: zsh-users

Hi,

> There is nothing about this, that would improve the behaviour of a
> simple for loop like
> 
>   for i in *; flac -- $i
> 
> (That's `short_loops' syntax, which is on by default in zsh. And it
> relies on `sh_word_split' being unset, which is also the default
> behaviour in zsh.)

I agree to this. Also it's nice to pass a variable without being
required to always specify it as ${foobar[@]}. Even better: to remind
myself of the fact that a for loop often deals with arrays I became
used to the following syntax:

for i (*) echo $i

and

for i ($foobar) { command1; command 2 || print "command 2 failed!" }

and

if [[ -n $foo ]] {
  bar
} else {
  baz
}

These are arbitrary examples of course; my point is that this syntax
makes scripts more readable to me than the agonising

if foo
then
  bar
else
  baz
fi

Especially with vim that highlights the opposite char ({) when you move
to the original char (}).

> Worse, it's *less* robust, because it's treating newline characters
> specially, although they are perfectly legal characters in a file name
> (albeit not very common ones). Also, if the user has an alias in
> place, like say,
> 
>   alias ls='ls -F'
> 
> ...that is not going to work either, because that will cause ls to
> append a / to directory names, a * to executable files and so on.

I remember trying to use aliases in a script. I don't think this works,
I changed them to functions at least. But yes I do agree on this, here
it even became a sport to minimise the use of external commands as much
as possible.

With zsh these tasks are often trivial. I suppose we all love examples
that show zsh's power and what I found great is that even sed and awk
can easily be replaced: 

cat $foobar | sed 's,Alice,Bob,g')  versus
${foobar/Alice/Bob}  (yes, bash can do this, too)

cat /proc/sys/kernel/version | awk '{print $2}'  versus
${$(</proc/sys/kernel/version)[(w)2]}.

> I know there are HOWTOs and tutorials online, that advocate constructs
> like that. And even worse ones, like "for i in `ls`; do...". But that
> doesn't make them good examples of shell programming.

Awfully written shell scripts have this much too often.

> I don't mean to offend with this reply. And I hope that my point is
> making sense to you. I've written about this in the past² (but it's in
> German) and so has the guy who maintains the FAQ for #bash (the IRC
> channel for GNU bash on freenode)³. Refer that that for more details
> on parsing the output from `ls'.

Additionally - it's a bit odd to prefer anything else above zsh's own
powerful globbing abilities. I have used 'ls -dl /proc/**/*keyword*(.)'
so often. I've often wondered if there is a Linux distribution using
zsh as its default shell for users and distribution specific stuff like
init scripts.

I found your email nice to read, Frank.

Ciao,
-Mark.


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2012-02-22 23:51 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-02-20 18:16 somehow offtopic: looping filenames meino.cramer
2012-02-20 18:38 ` Frank Terbeck
2012-02-20 19:05 ` Bart Schaefer
2012-02-21 12:35   ` Stephen Blott
2012-02-21 13:35     ` Frank Terbeck
2012-02-22 23:41       ` Mark van Dijk

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).