It's like people saying you don't need to escape SQL values because they come from constants. Yes, they do... today.
It's not just quoting either. It's setting the separator value and reverting it correctly. It's making sure you're still correct when you're in a function in an undefined state. It's a lot of overhead in larger projects.
For example, there is no way to store the `a b "c d"` in a regular variable in a way where you can then call something similar to `ls $VAR` and get the equivalent of `ls a b "c d"`. You can either get the behavior of `ls a b c d` or `ls "a b c d"`, but if you need `ls a b "c d"` you must go for an array variable with new syntax. This isn't necessarily a big hurdle, but it indicates that the concepts are hard to grasp and possibly inconsistent.
var=( a b "c d" )
ls "${var[@]}"
POSIX shell can get you what you want with eval: var='a b "c d"'
eval "ls $var"
There is also one array variable in POSIX shells, the argument list: set -- a b "c d"
ls "$@" $ exec(‘ls’, ‘-l’, ‘A B C’)
Maybe that’s unrealistic? I mean, if the shell was like that, it probably wouldn’t have exec semantics and would be more like this with direct function calls: $ ls(ls::LONG, ‘A B C’)
Maybe we would drop the parentheses though — they can be reasonably implied given the first token is an unspaced identifier: $ ls ls::LONG, ‘A B C’
And really, given that unquoted identifiers don’t have spaces, we don’t really need the commas either. Could also use ‘-‘ instead of ‘ls::’ to indicate that an identifier is to be interpreted locally in the specific context of the function we are calling, rather than as a generic argument. $ ls -LONG ‘A B C’
If arguments didn’t have spaces, you could make the quotes optional too.QED
The much bigger problem is that spaces make text-only commands compose badly.
$ ls -l `find ./ -name *abc*`
Is going to work very nicely if file names have certain properties (no spaces, no special chars), and it's going to break badly if they don't. Quoting is also very simple in simple cases, but explodes in complexity when you add variables and other commands into the mix. ls -l ${find ./ name *abc*}
# return the result as a single string
ls -l @{find ./ name *abc*}
# return the result as an array (like Bourn shell)
So in the first example, the command run would look something like: ls -l "foo abc bar"
whereas in the second it would behave more like Bourne shell: ls -l foo abc bar
As an aside, the example you provided also wouldn't work in Bourne shell because the asterisks would be expanded by the shell rather than `find`. So you'd need to quote that string: ls -l `find ./ -name "*abc*"`
This also isn't a problem in murex because you can specify whether to audo-expand globbing or not.With POSIX shells you end up with quotation mark soup:
ls -l "`find ./ -name '*abc*'`"
(and we're lucky in this example that we don't need to nest any of the same quotation marks. It often gets uglier than this!)Murex also solves this problem by supporting open and close quote marks via S-Expression-style parentheses:
ls -l (${find ./ -name (*abc*)})
Which is massively more convenient when you'd normally end up having to escape double quotes in POSIX shells.---
Now I'm not trying to advocate murex as a Bash-killer, my point is that it's specifically the design of POSIX shells that cause these problems and not the way Unix pipelines work.
Pipelines to the rescue. If you used a pipeline instead of shell expansion, it can deal with spaces just peachy.
$ find . -name "*abc*" -print0 | xargs -0 ls -l
There's no argument that bash (and other shells) make dealing with spaces and quotes troublesome. That has nothing to do with pipelines.My point wasn't specifically about find, but about the problems of text and other unstructured input/output in general.
Update: reading a bit around the internet, it looks like it's not possible to do something like this :
find / -print0 | \
grep something | \
xargs -0 cat
As grep will mangle the output from find -print0.