Re: Reintroducing fish, the friendly interactive shell

Stephane Chazelas skrev:

On 9 Mar 2006 05:17:32 -0800, liljencrantz@xxxxxxxxx wrote:
In zsh, RE's * is #, RE's + is ##, RE's ? is (...|) (or
nothing). That makes zsh patterns to involve fewer keystrokes.
That also means the grouping can be implemented as (...).
Note that zsh implemented globbing attributes (like case
insensitive, approximate matching, activation of backreference
the same way as perl does: (#...) in zsh, (?...) in perl,
because # can't otherwise follow a ( in zsh the same way as ?
can't otherwise follow a ( in perl.

Isn't this just a new syntax for regular expressions?

It is. It is also one that is compatible (mostly) with historical
globbing and is more suitable for matching filenames than the
standard REs.

How is it more suitable for filename matching?

Why not simply
use grep to provide you with real regexps?

grep doesn't do filename expansion, and basic REs are not handy
to match filenames.

Grep uses find (or the shell, or some other program) to do the filename
matching. As to regex unsuitability for filename matching, I'd like to
see a justification of this.

The unix philosphy of using
a set of orthogonal commands that do one thing each, and connecting
them using pipes is very powerful. Globbing is a _very_ useful hack
that breaks this philsophy by allowing you to perform some types of
very _simple_ matchings inside the shell. The above seems to make
globbing into this huge, hairy beast that can be used for almost
anything find, grep, head, tail, ls and sort do, with a syntax that is
as readable as Perl. What is the point of stuffing all this stuff into
the shell that can be implemented in a more readable and even more
poerful way using external commands?

Maybe because with a few keystrokes, you can do more reliably
than you could have done in a 20 line unreadable script.

How about writing a script that is only a few keystrokes long then?
(See below)

Also, at the prompt, you don't read what you type, it's
write-only. For scripts, zsh has longer forms that you might
consider more readable (like kshglob). Note that zsh also
supports perl regexp (with a builtin in a loadable module).

Why the fixation with avoiding external commands?

Yes, in that case, this doesn't make more sense. the pcre module
is sold as an "example module" though. It may come handy if you
don't have perl.

ls -S (find . -mmin -120)|head
(or ls -S `find . -mmin -120`|head if you haven't switched to fish yet)

ls -Sd and it doesn't select regular files (or symlinks to
regular file), and it makes the assumtion file paths don't have
newline or blank characters. And -S and -mmin are not Unix.

Nor is zsh Unix. To get what you want you still have to install
non-standard commands. It is easy (and common) enough to install the
GNU toolchain on e.g. Solaris. You can do it in ~ if you have the
space. You can do a 'make dist' to various common architectures and
store the tarballs on a public ftp to make for a quick install on
almost any machine with internet access.

I do not see how using a nonstandard shell is more portable than using
nonstandard shell commands.

As to -S an -mmin, they are not standard, but they are not uncommon
either. E.g. FreeBSD implements both.

Handling blanks was an oversight on my part, the fish code handles this
correctly, the Posix version needs IFS fidling or some other solution.
Another nice way of solving this would be for ls to accept the list of
files to print from stdin, the same way most other unix commands do.
This should obviously only be used after detecting thet stdin is not a
tty. Newlines is a bit tougher, in my opinion the correct solution
would be to ban the use of newlines in filenames.

You use a pipeline containing find, ls and head. That's the beauty of

But it's broken by design. Either Unix should prohibit all types
of non-alnum chars in filenames, or command substituion and all
the standard filtering utilities should be changed to be able to
cope with a NUL character separator (zsh is the only shell that
supports the NUL character (maybe fish does as well?)).

That's a bit strongly worded, isn't it? Why is the idea of a pipeline
broken by design since most commands don't handle nulls in filenames?
The null problem is simply an unfortunate sideeffect of the choice of
string format in C, it is not a fundamental property of a pipe. And
unless I'm mistaken, the null character is illegal in filenames anyway,
since all filenames on Unix filesystems are specified to the operating
system using null-terminated strings.

Null handling seems to be a spot where zsh outshines fish though, fish
does not yet support nulls in strings. There is a pretty clear plan for
the changes needed for fish to do so, though.

use one tool to solve each part of the task, and string them
together in a pipeline to solve a nearly infinite number of problems
with a small set of simple tools.

Yes, in theory it's nice. zsh gives you something more powerful
that doesn't use that framework. You're free to use grep and the
like with zsh. I made my choice ;).

Implementing what I would qualify as a hack (no offence meant) in the
shell globbing is a quick and easy way to solve the problem, but in my
opinion it makes the language special purposed and clumsy, it makes the
architechture unwieldly and it makes the codebase unmaintainable. Long
term, I think it's the wrong thing to do.

Lets fix bugs and add the missing features to the free versions of
common commands, so that anybody can get a working system anywhere
using any shell.

Also notice that the find command is comparable in length to the zsh
version espacially if you use 'echo' to output it to stdout.

On a GNU system, the strict equivalent of zsh's would be:

eval "set -- $(find . -name '*.c' \( -type f -o -type l \) --exec \
find {} -follow -prune -type f -mmin -120 -printf '%s:\p\0' \; |
sort -rnz | awk -v'RS=\0' '
function escape(s) {
gsub(/'\''/, "'\''\\\'\'\''", s)
return "'\''" s "'\''"
{NR <= 10} {
sub(/[^:]*:/, "")
printf " %s", escape($0)

and there's no Unix equivalent.

Well zsh is not Unix either, so I don't see that as relevant here.

Is that more readable or short or ortogonal?

No, but I'm sure there are equaly complicated and unwieldly
zsh-specific ways of writing the same thing.

Instead of using the rather complicated code like the script you
provided, you can get any behaviour you want WRT symlinks, directories,
fifos, etc. by using the -type switch for find and the script from my
original mail. Fish correctly handles spaces and nulls are illegal in
filenames so these are no problem. The only outstanding issue is the
problem with newlines, where I would simply suggest implementing a
strict no newlines in filenames policy.

It will probably not work with old versions of gawk.