3 ms·
Indeed, and the shell lives and breathes spaces. Arrays of arguments are created every time one types a command. Without spaces-as-magic we’d be typing things
by gorgoiler 6y ago
Indeed, and the shell lives and breathes spaces. Arrays of arguments are created every time one types a command. Without spaces-as-magic we’d be typing things like this all the time:
$ 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
- tsimionescu 6y agoI don't think this is the problem people usually complain about. 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.
- hnlmorg 6y agoThat's still just a shell problem since the shell is expanding `find` and placing the unquoted result into the command line. Some non-POSIX shells don't have this issue. For example with murex you could use either of these two syntaxes: 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.
- bregma 6y agoAh, more problems with shell expansion and substitution. 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.
- jcranmer 6y agoAnd note that, all the way in my original argument, I complained that every command used a different way of spelling that changed delimiter character.
- tsimionescu 6y agoDoes every unix utility suport -print0 or similar? 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.