While I acknowledge the existance of shell hell, I don't think your example is evidence of it. You highlight the fact the some versions of test allow for '==' to mean the same thing as '='. This, I'm sure, was done to prevent a common, harmless user error from causing trouble. All you have to do to steer clear of such problems is not to rely on 'test' to support non-standard options.
There is however another problem related to the one you outline above. bash, zsh and probably most of the other shells in your example do not use the standard test command, but do instead use a builtin with the same name. I think including dozens of standard unix commands such as kill, test and printf in the shell binary as builtins is a design mistake. It breaks the unix tradition of doing one thing and doing it well. At least bash has had some trouble with fd redirections and builtins. A bug in a builtin may cause the entire shell to crash. When the user switches shells or invokes a program directly, and not through the shell, he/she may find out that the programs syntax has changed!
For the reasons outlined above, I think the only commands that the shell should provide as builtins are the ones that can not be implemented as a separate command, such as cd, exit and if.
Re:ZSH rocks except for one misfeature
on
From Bash To Z Shell
·
· Score: 2, Insightful
I think this is a good illustration of one of the major problems with zsh. To get a decent history file with all the cool features, you have to add 9 different commands to you configuration file.
To get a goob tab completion, with a good pager, etc, you need another boatload of commands. You will also want to redefine some keyboard shortcuts to more powerful versions of the same commands and install a few nifty add-ons.
So suddenly you have spent a few hours creating a 100+ lines long configuration file just to enable some of the common zsh options. If dedicating your life to tweaking your shell sounds like fun, then go ahead. But most people have better things to do with their time.
I've experienced this problem on Solaris as well. I usually solve this by changing the PATH.
If that doesn't work, I would propose the use of aliases instead of environment variables to point to the correct command. But if you want to be all hardcore and use eval, quoting is much less of a minefield in fish, because of the simpler quoting rules.:-)
for tif in *.tif tiftoppm $tif | cjpeg >(basename $tif.tif).jpg end
Please note that the fish version will work with any files, but the bash version you posted will break on files with spaces because of the braindead tokenizing support in Bourne shells.
I am planing on doing the following mouse integration in fish:
Click with mouse to move cursor
Select completions using mouse cursor
There is already an extension script for zsh which lets you move the cursor using the mouse, which can be downloaded here. (Note: I am not the author of the zsh mouse support. )
I just noticed you said _galobal_ alias, not glob alias. My bad.
I looked global aliases up, and I must say that I don't like the idea. There is far to little benefit and far to many ways to shoot yourself in the foot. Sorry.
I use it a lot to see that i got all the switches to commands right. I keep forgetting if it's supposed to be 'mplayer --fs' or 'mplayer -fs', and things like that.
Fish uses a builtin command called 'set' to assign variables. Instead of 'foo=bar' you write 'set foo bar'.
Using set is slightly wordier, and may look a bit strange to people who are used to 'foo=bar', though csh users should feel comfortable. The reason for doing it this way is to make the language uniform. In fish _everyhing_ is a command. for and switch are just builtin commands, they follow the same syntax rules as any other command. I feel that by making the syntax small and uniform, fish is easier to learn.
If I where to use a syntax using '=', it would be '$foo = bar', since a variable should not be allowed as the first token of a command anyway. If you _want_ to execute the contents of a variable, use eval.
BTW, fish uses ';' and newlines as command delimiters, so you do _not_ need to have semicolons at the end of the lines like in my example. I put them there out of habit.
Belive me, I know the difference between '$foo' and "$foo" and `$foo`. I just don't think it is a good syntax. The fact that every time I write a shellscript, I have to go over it afterward to see that every time I use a variable, it is enclosed with quotes drives me nuts. The fact that
for i in a b c; do; echo $i; done
is a syntax error (too many ';') is also stupid.
I _know_ that variable assignments are whitespace sensitive, but in my opinion no good language should be.
I don't like the fact that if blocks end with 'fi', case blocks with 'esac', but loop block end with 'done'. Even more disturbing is the subblocks of a case statment. they end with ';;'. Where is the logic?
Fish has a consistent block syntax borrowed from MATLAB:
for i in foo bar baz;
echo $i; end;
while true;
echo fish rules! end;
if [ $SHELL = fish ];
echo yay; end;
switch $SHELL
case "f*";
echo could be a fish
case "*"
echo not a fish end;
I could make a list ten pages long of issues that I have with bash syntax. fish does _not_ fix all of these issues, and I'm sure it introduces a few new ones. But I firmly belive that it has a much saner syntax. And I am continually trying to improve the fish syntax until fish is to bash what Python is to Intercal.
I goggled '"glob alias" zsh' and a few other strings, but came up with no information. If you could describe what a glob alias is, I will be happy to tell you if fish supports something like it.
Syntax highlighting can give you a great deal of information. I have written a shell called fish, that syntax highlights the commands as you are typing them. What I find useful about this is that fish colors potential errors in red. Mistyped commands, non-existant options, reading from non-existing files and loads of other errors can be identified by just glancing on your screen.
I was referring to what the result of globbing on the different parameters, I was not talking about what would be the result of trying to use values like '$foo' as a command, which does not make sense.
Like a previous poster pointed out, echo $foo does not do what you think it does, it just happens to work in your example since your string does not contain spaces.
I think both zsh and bash could use a redesign. The syntax is crufty, with stupid variable assignment syntax ('foo = bar' is not the same thing as 'foo=bar'? '$foo' is not the same thing as `$foo` or "$foo"?), insufficient tab-completion support and very few features enabled by default. I have written a shell called fish. It has lots of new features. Check it out.
Your link to Godwins statement clearly states that this is not the first time he made it. So you have not supplied any evidence that someone beat Godwin to it.
Yeah, what the author meant with crash proof is that when a crash happens, only the user whos request the application was processing gets an error, and because of the shared closures, the crash may not even be that bad for the one user.
This scenario breaks down when: there is a bug in the shared classes or the shared closures implementation, when there is a bug causing corrupt data to be written to the shared closuers, when one or more processes trigger a bug which cause them to hog a scarce system resource like memory or CPU time, when a OS bug or a hardware failiure is encountered, etc, etc, etc.
The ideas outlied are sound for an extremely high availability system, but they are not enough to make the clain unbreakable.
Some improvements to the outlined strategy: Use a validator to check that the information written to the shared closures is always correct. Mirror the shared closures to another computer. Have a backup computer which automatically picks up if the first one falls down.
You once mentioned in a news post that at some point you accidentally sold the rights to PA. Could you make up an amusing anecdote loosely based on this premise?
It's called SELinux, it was written byt the NSA, and even without it you already have pretty fine grained control over file permissions using groups and file permissions. What SELinux gives you is the ability to also restrict such things as network access, the right to fork, run execve, switch userid, etc. SELinux can grant these rights not only based on userid, but also on which program is run.
In the end, what this gives you is a system where, if a process using a properly configured SELinux has been taken over (0wn3d), it can't do anything other than screw up it's own job, unless it figures out how to fool SELinux.
While I acknowledge the existance of shell hell, I don't think your example is evidence of it. You highlight the fact the some versions of test allow for '==' to mean the same thing as '='. This, I'm sure, was done to prevent a common, harmless user error from causing trouble. All you have to do to steer clear of such problems is not to rely on 'test' to support non-standard options.
There is however another problem related to the one you outline above. bash, zsh and probably most of the other shells in your example do not use the standard test command, but do instead use a builtin with the same name. I think including dozens of standard unix commands such as kill, test and printf in the shell binary as builtins is a design mistake. It breaks the unix tradition of doing one thing and doing it well. At least bash has had some trouble with fd redirections and builtins. A bug in a builtin may cause the entire shell to crash. When the user switches shells or invokes a program directly, and not through the shell, he/she may find out that the programs syntax has changed!
For the reasons outlined above, I think the only commands that the shell should provide as builtins are the ones that can not be implemented as a separate command, such as cd, exit and if.
I think this is a good illustration of one of the major problems with zsh. To get a decent history file with all the cool features, you have to add 9 different commands to you configuration file.
To get a goob tab completion, with a good pager, etc, you need another boatload of commands. You will also want to redefine some keyboard shortcuts to more powerful versions of the same commands and install a few nifty add-ons.
So suddenly you have spent a few hours creating a 100+ lines long configuration file just to enable some of the common zsh options. If dedicating your life to tweaking your shell sounds like fun, then go ahead. But most people have better things to do with their time.
I've experienced this problem on Solaris as well. I usually solve this by changing the PATH.
:-)
If that doesn't work, I would propose the use of aliases instead of environment variables to point to the correct command. But if you want to be all hardcore and use eval, quoting is much less of a minefield in fish, because of the simpler quoting rules.
The same command in fish:
.tif).jpg
for tif in *.tif
tiftoppm $tif | cjpeg >(basename $tif
end
Please note that the fish version will work with any files, but the bash version you posted will break on files with spaces because of the braindead tokenizing support in Bourne shells.
There is already an extension script for zsh which lets you move the cursor using the mouse, which can be downloaded here. (Note: I am not the author of the zsh mouse support. )
I just tried to tab complete 'echo ?li' in a directory containing files like 'alias.c' and 'alias.h'. zsh did not find any completions.
I tried using this both with the default completion and using the new 'compinit' completions. Nothing.
Is there yet _another_ command you have to give to zsh in order to make it work the way it should by default?
*doh*
I just noticed you said _galobal_ alias, not glob alias. My bad.
I looked global aliases up, and I must say that I don't like the idea. There is far to little benefit and far to many ways to shoot yourself in the foot. Sorry.
I use it a lot to see that i got all the switches to commands right. I keep forgetting if it's supposed to be 'mplayer --fs' or 'mplayer -fs', and things like that.
Fish uses a builtin command called 'set' to assign variables. Instead of 'foo=bar' you write 'set foo bar'.
Using set is slightly wordier, and may look a bit strange to people who are used to 'foo=bar', though csh users should feel comfortable. The reason for doing it this way is to make the language uniform. In fish _everyhing_ is a command. for and switch are just builtin commands, they follow the same syntax rules as any other command. I feel that by making the syntax small and uniform, fish is easier to learn.
If I where to use a syntax using '=', it would be '$foo = bar', since a variable should not be allowed as the first token of a command anyway. If you _want_ to execute the contents of a variable, use eval.
BTW, fish uses ';' and newlines as command delimiters, so you do _not_ need to have semicolons at the end of the lines like in my example. I put them there out of habit.
Belive me, I know the difference between '$foo' and "$foo" and `$foo`. I just don't think it is a good syntax. The fact that every time I write a shellscript, I have to go over it afterward to see that every time I use a variable, it is enclosed with quotes drives me nuts. The fact that
for i in a b c; do; echo $i; done
is a syntax error (too many ';') is also stupid.
I _know_ that variable assignments are whitespace sensitive, but in my opinion no good language should be.
I don't like the fact that if blocks end with 'fi', case blocks with 'esac', but loop block end with 'done'. Even more disturbing is the subblocks of a case statment. they end with ';;'. Where is the logic?
Fish has a consistent block syntax borrowed from MATLAB:
for i in foo bar baz;
echo $i;
end;
while true;
echo fish rules!
end;
if [ $SHELL = fish ];
echo yay;
end;
switch $SHELL
case "f*";
echo could be a fish
case "*"
echo not a fish
end;
I could make a list ten pages long of issues that I have with bash syntax. fish does _not_ fix all of these issues, and I'm sure it introduces a few new ones. But I firmly belive that it has a much saner syntax. And I am continually trying to improve the fish syntax until fish is to bash what Python is to Intercal.
I goggled '"glob alias" zsh' and a few other strings, but came up with no information. If you could describe what a glob alias is, I will be happy to tell you if fish supports something like it.
It is GPL'ed. :-)
Syntax highlighting can give you a great deal of information. I have written a shell called fish, that syntax highlights the commands as you are typing them. What I find useful about this is that fish colors potential errors in red. Mistyped commands, non-existant options, reading from non-existing files and loads of other errors can be identified by just glancing on your screen.
</shameless plug>
I was referring to what the result of globbing on the different parameters, I was not talking about what would be the result of trying to use values like '$foo' as a command, which does not make sense.
Like a previous poster pointed out, echo $foo does not do what you think it does, it just happens to work in your example since your string does not contain spaces.
Yes. Use (...) for subshells. I hope you'll like fish!
No, you are wrong.
In bash:
$foo gives you the contents of variables foo as a list of space-separated strings. "foo bar" becomes "foo" and "bar".
"$foo" gives you the contents of variable foo as a single variable. "foo bar" remains "foo bar".
'$foo' gives you the string "$foo".
`$foo` executes the command pointed to by the variable foo in a subshell. If foo has the value "ls" executes the "ls" command.
In fish:
$foo gives you the contents of variable foo as a single string, "foo bar" remains "foo bar".
"$foo" and '$foo' both give you the string "$foo".
And those are all the quoting styles allowed in fish.
Awesome! =D
I think both zsh and bash could use a redesign. The syntax is crufty, with stupid variable assignment syntax ('foo = bar' is not the same thing as 'foo=bar'? '$foo' is not the same thing as `$foo` or "$foo"?), insufficient tab-completion support and very few features enabled by default.
I have written a shell called fish. It has lots of new features. Check it out.
</shameless plug>
fp?
Your link to Godwins statement clearly states that this is not the first time he made it. So you have not supplied any evidence that someone beat Godwin to it.
Yeah, what the author meant with crash proof is that when a crash happens, only the user whos request the application was processing gets an error, and because of the shared closures, the crash may not even be that bad for the one user.
This scenario breaks down when: there is a bug in the shared classes or the shared closures implementation, when there is a bug causing corrupt data to be written to the shared closuers, when one or more processes trigger a bug which cause them to hog a scarce system resource like memory or CPU time, when a OS bug or a hardware failiure is encountered, etc, etc, etc.
The ideas outlied are sound for an extremely high availability system, but they are not enough to make the clain unbreakable.
Some improvements to the outlined strategy: Use a validator to check that the information written to the shared closures is always correct. Mirror the shared closures to another computer. Have a backup computer which automatically picks up if the first one falls down.
To each his own. Some people prefer dynamically typed langages, you know. Not just for developing websites either.
Get over yourself. He's kidding. 'Visable' and 'comvert' should be considered hints.
You once mentioned in a news post that at some point you accidentally sold the rights to PA. Could you make up an amusing anecdote loosely based on this premise?
It's called SELinux, it was written byt the NSA, and even without it you already have pretty fine grained control over file permissions using groups and file permissions. What SELinux gives you is the ability to also restrict such things as network access, the right to fork, run execve, switch userid, etc. SELinux can grant these rights not only based on userid, but also on which program is run.
In the end, what this gives you is a system where, if a process using a properly configured SELinux has been taken over (0wn3d), it can't do anything other than screw up it's own job, unless it figures out how to fool SELinux.