amarshall
6 hours ago
Or you can just…not quote the tilde. Folks always seem to reflexively quote “strings” in Bash while not realizing that (almost) everything is a string and most strings are not quoted and it would be odd to do it (e.g. no one is doing `"ls" "-a" "foo"`).
isityettime
3 minutes ago
This feature, or at least the syntactic unit in question has a name here "bare words". You also have these in some contexts in Perl and Ruby, YAML, and probably some other languages, idk.
I've also seen this even with people who seem like generally competent shell users. Idrgi
Cockbrand
5 hours ago
I feel like this is common knowledge and should not be worth mentioning. But then it apparently is not common knowledge, as the article proves.
Have I run into this at some point?
I certainly have.
Have I learned to quote better and only where appropriate from it?
I certainly have.
Bourne compatible shells take a while to learn and require some experience. This won't change, but alternatives exist, with their own caveats.
MathMonkeyMan
5 minutes ago
Almost nobody that I've ever worked with knows how the shell works. I send them [the docs][1] but what kind of world would this be if people read the docs? Also, not exactly a page turner.
[1]: https://pubs.opengroup.org/onlinepubs/9799919799/utilities/V...
dylan604
6 hours ago
Unless you're running a shell command from python. That was the first time I saw a command string broken down into "string" arguments for every thing like that.
thwarted
6 hours ago
In that case, you're not running a "shell command" from python, you're passing arguments to exec. A shell command would be a string interpreted by the shell, and you'd use that for shell syntax things like having the shell do variable interpolation or redirections as part of executing the command.
vips7L
6 hours ago
Or just stop using bash. It’s a terrible language to write and has tons of footguns.
yjftsjthsd-h
4 hours ago
For the things shell is good at (running other commands, pipes, and shuffling files), I have yet to find anything even close to as good.
vips7L
3 hours ago
A different shell??? Nushell, fish, powershell, etc.
yjftsjthsd-h
3 hours ago
Oh, you mean bash specifically. Then yeah, that's reasonable enough. Although I agree with the other commenter that sh/bash have the advantage of ubiquity.
lelandbatey
3 hours ago
None of those have the #1 best thing bash is good at: bash is already installed, nushell and fish are not.
Powershell is, as I understand it, not available on Linux but is omnipresent on Windows, so hopefully the windows folks can use it like they would bash.
barrkel
2 hours ago
PowerShell works on Windows because of WMI, to a first approximation.
Because Windows is tied together through APIs and databases and not text files (unlike Linux), everything is text is not as useful as something that can talk objects. And a lot of Windows is object oriented, from the window message dispatching system through COM and down to NT's object manager.
yjftsjthsd-h
3 hours ago
No, powershell runs on Linux, it just sucks because it wants objects and everything on *nix speaks streams of text.
hnlmorg
3 hours ago
I agree that shells are uniquely good for that but there are plenty of better shells than Bash.
Such as Fish, nushell, Elvish, or the project I help maintain, “murex”
bornfreddy
3 hours ago
None that I can rely on being available wherever I see a terminal. It's bash or sh as far as I'm concerned.
xigoi
2 hours ago
Fortunately, 99.9% of the time I’m on my computer, where I can install whatever I want.
ifwinterco
an hour ago
Then you ssh into an instance and have to remember how bash/sh work
gavmor
38 minutes ago
At what point does an alternate shell get baked into the image?
shevy-java
3 hours ago
I did.
Ruby replaced all my shell needs. Almost 25 years ago. I even have a shell written in ruby (it handles both bash-like behaviour as well as ruby code as-is); admittedly it is not quite perfect for everything, but I improve on it steadily. And it works on Windows too, which was one reason I wrote it in the first place (need to have it work via cmd.exe as-is).
Never looked back to shell. It is too awful to use.
CodesInChaos
6 hours ago
Unfortunately half of its badness isn't isn't the shell itself, but the convention of how parameters are passed to processes on Unix systems.
hnlmorg
4 hours ago
That’s not correct because POSIX passes what is ostensibly an array of strings.
Windows, on the other hand, only passes one string. So it’s up to the application to choose how to handle whitespace, quotation marks, and other nuances with parsing parameters.
Variable expansion in Bash is lazy. But there’s no reason why variables cannot be tokenised so that strings with spaces aren’t treated as multiple parameters. And in fact that’s exactly how some other shells work, such as the one I maintain.
formerly_proven
5 hours ago
Array of arguments is vastly superior and more secure than every program/runtime inventing a slightly different way of splitting a command string into an array of arguments. No debate. A real problem is the related birth defect in ssh2.
akoboldfrying
5 hours ago
Well, the only other way I can think of that it could be done is the Windows way, whereby you pass the unparsed command line, spaces and all, as a string to the new process. And while this is arguably the cleaner interface, in practice it has meant even worse quote handling, since how -- or even whether -- double quotes are parsed now depends on the probably undocumented process startup code chosen by the program's compiler vendor.
Want to quote a command line that may already contain double quotes, in order to pass it as an argument to some other program? No, you don't. It isn't right to want that.
ChrisSD
3 hours ago
The other other way would be more structured. Arguments are not just an array, they also contain `--switch` and key/value pairs (e.g. `--key value` or `--key=value` depending on who you ask). One problem with the flat array approach is there's no way to distinguish a literal value starting with `-` from a switch, which means there needs to be some way to workaround that (and users have to remember the workaround; how often do people remember to use `rm -- "$FILENAME"`).
In practice almost every application does still need to do its own parameter parsing; a flat array is not enough.
sysguest
4 hours ago
yeah but... that convention is so much of a security/bug headache
sometimes, its footguns seem worse than javascript...
hope some typescript-like "typed shell" becomes mainstream someday
coldpie
4 hours ago
> hope some typescript-like "typed shell" becomes mainstream someday
The trouble with trying to invent a new, more robust shell language is you basically just end up re-inventing any number of scripting languages (eg Perl, Python, awk, ...), so you might as well use one of those.
hnlmorg
4 hours ago
Most regular programming languages aren’t well suited for shells because they have a verbose syntax due to their readability goals. But with a shell, the vast majority of times you’re typing in stuff that you have no intention of reading back ever again.
I’ve done a fair amount of research here and I actually think we do need a new programming language for the shell (and then I created one).
I wrote a blog about this problem: https://murex.rocks/blog/split_personalities.html#conclusion
coldpie
3 hours ago
Excellent article, thanks for the link. I do agree with the premise. But every time I write some Bash code and think there should be a better way to do this, I ask myself why I don't just learn Perl. I dunno. Feels like inventing another solution would just hit the old "there are now 14 standards" problem where it would solve some problems but introduce others (see: PowerShell).
hnlmorg
3 hours ago
I don’t disagree with you per se. But if the new shell solves enough annoying problems then I think it has merit in existing.
ravenical
3 hours ago
> hope some typescript-like "typed shell" becomes mainstream someday
Might want to check out nushell (https://www.nushell.sh/)
colejohnson66
an hour ago
PowerShell
malux85
4 hours ago
The widwit answer: "Dont do X" (and nothing more)
The enlightened answer "You should use A, B or C for these reasons"
Even though bash is installed on many systems, I try to encourage people to use better designed shells that have less of these footguns :
Fish (https://fishshell.com/): No implicit word splitting : spaces in variables won't unexpectedly become separate arguments.
Zsh (I use this: https://ohmyz.sh/): Arrays start at 1 by default, but crucially, unquoted variables don't implicitly split into multiple arguments.
Nushell (https://www.nushell.sh/): Passes structured tables and records between commands : avoids fragile parsing of text with awk/grep.
paulddraper
6 hours ago
People quote both too often and too little.
GENERAL RULE
1. Double-quote dollar sign expressions, and nothing else.
foo
"$bar"/foo
baz:"$(cat example.txt)"
exec cmd "$@"
2. Single-quote words with a literal special character, and nothing else. 'Die Hard'
'ke$ha'
---I should point out that the author's example is NOT fixed by different quoting though.
# original
export PATH="$PATH:~/.local/bin/"
# without unnecessary quotes
export PATH="$PATH":~/.local/bin/
Because tilde expansion only happens at the beginning of the word.gray_-_wolf
an hour ago
> I should point out that the author's example is NOT fixed by different quoting though.
Sure, but I would say you almost always want to add to the start of the PATH, not to the end.
JdeBP
5 hours ago
The Z shell's, C shell's, and others's syntaxes for setting the PATH environment variable via a shell array variable alias also does the tilde expansion.
path=( $path ~/bin )
It's worth noting, also, that the path and manpath settings in login.conf(5) expand leading tildes in individual search path items.* https://man.freebsd.org/cgi/man.cgi?query=login.conf&sektion...
So putting the addition of things like ~/bin to PATH in /etc/login_conf and ~/.login_conf instead of shell scripts is another way to address it.
:path=~/bin /usr/local/bin /usr/pkg/bin /usr/bin /bin:
It's particularly handy when there are multiple login shells in use.cr125rider
6 hours ago
The trick is to quote explicitly and correctly. “ and ‘ are different.
dylan604
6 hours ago
why would you use smart quotes in a terminal like that?
tom_
6 hours ago
They probably fell foul of some browser text box auto-correct.
dylan604
4 hours ago
' "
I don't use WYSIWYG editors anymore, so I have to remind myself to use those when writing raw HTML text. Although, most browsers correct raw ' and " symbols in text now, I still try to use them to have compliant HTML
airstrike
6 hours ago
why would anyone use smart quotes ever
mpyne
5 hours ago
They are typographically the right thing to have been using all along.
Using ' and " to pretend to be ‘/’ or “/” is on par with the typewriter days where people would use the l key to stand in for 1 also. A justifiable approximation when technology limitations prevented using the real deal, but an approximation all the same.
dmd
4 hours ago
In fact, if we had been using left and right quotes from the beginning in shells, most “quoting problems” go away, as they’re all inherently rooted in not being able to know what level of nesting a quote character is at.
airstrike
an hour ago
Can't that be handled by the typesetting/rendering software and displayed appropriately regardless of which specific character was typed?
Dylan16807
5 hours ago
Except l has a specific meaning that isn't 1, while the entire purpose of ' and " is quoting (and apostrophe).
The equivalent of l for 1 is doing font-specific pseudo smart quotes with ` and '
mpyne
3 hours ago
" and ' are themselves conjoined with other uses.
" can be inches or arcseconds from cartography.
' can be feet (of measure) or arcminutes from cartography.
These actually all have slightly different symbols, and the symbols for the left/right quotation marks are actually farthest from this approximation, even if they are the most frequent usage.
It’s always been wrong in some respect to use a single available symbol to emulate three or more different typographical tasks, but quotation marks may actually be the one where the emulation is the most wrong.
opello
3 hours ago
That equivalency only holds if there is a visual distinction in the output between the l and the 1. There often wasn't when this practice was popular.
thaumasiotes
4 minutes ago
As others have commented, for the same reason that we use smart parentheses instead of the more utilitarian |.
Grimeton
2 hours ago
You need to read the manual.
chasil
4 hours ago
I think the appropriate method by POSIX rules would be:
export PATH="$PATH:"~/.local/bin
I may be wrong. If I'm not, that works in any POSIX-compliant shell.Edit: this appears to work properly with mksh on my phone:
:/ $ export PATH="$PATH:"~/.local/bin
:/ $ print $PATH
/product/bin:/apex/com.android.runtime/bin:/apex/com.android.art/bin:/system_ext/bin:/system/bin:/system/xbin:/odm/bin:/vendor/bin:/vendor/xbin:~/.local/binyencabulator
4 hours ago
That's a literal ~ in your path, the exact problem the blog post talks about.
Your use doesn't count as a "word", per man bash. Tilde is only expanded to home at the start of a typically whitespace-separated word, and your tilde is in the middle of one.
> If a word begins with an unquoted tilde character (‘~’), all of the characters up to the first unquoted slash (…) are considered a tilde-prefix. (…)
> word A sequence of characters considered as a single unit by the shell. Also known as a token.
chasil
2 hours ago
My initial syntax does work in dash (and bash), but all these shells appear to rely on expanding ~ inside a word, that your source asserts is not POSIX (which I do not contest).
Perhaps a succinct and compliant expression could be:
export PATH="$PATH:$(printf %s ~/.local/bin)"
That comes at the cost of forking a subsell.Edit: 2.6.1 Tilde Expansion in the POSIX standard says that ~ may be expanded "following any unquoted <colon>".
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V...
That being so, the most succinct and compliant version is my first variant, with the colon moved outside the quotes:
export PATH="$PATH":~/.local/bin
Thank you for prompting me to look this up.