Timeline for Backticks giving different result than pasting result
Current License: CC BY-SA 4.0
16 events
| when toggle format | what | by | license | comment | |
|---|---|---|---|---|---|
| Jan 4, 2022 at 3:12 | vote | accept | Erhannis | ||
| Jan 3, 2022 at 19:58 | comment | added | ilkkachu | @Erhannis, not everything else, notably it also doesn't process expansions and operators. You could have a file called "hello $(bad command) && echo foo", and it would work fine with rm ./*, or indeed if the name was contained in a variable, and you did rm "$filename". Zsh doesn't do word splitting on variables by default, (err, but I think it does on command substitutions, for some reason) and it has better tools on controlling it too, and for using the output of e.g. find -print0. | |
| Jan 3, 2022 at 19:55 | comment | added | ilkkachu | See also Why does my shell script choke on whitespace or other special characters?, When is double-quoting necessary?, mywiki.wooledge.org/WordSplitting | |
| Jan 3, 2022 at 19:55 | comment | added | Erhannis | @ilkkachu No quotes, yes, just everything else. :P Anyway, I think we're on the same page now. And thank you for acknowledging that the-way-things-are is largely due to the-way-things-were, not simply the-way-things-should-be. So, does zsh behave differently than bash does, then? | |
| Jan 3, 2022 at 19:54 | comment | added | ilkkachu | And no, ls $(echo *.txt) wouldn't work if the glob gave any filenames with whitespace (or something like *.txt which itself is a valid filename...). And that's exactly because the result of $(echo ...) is word-split, while the plain glob *.txt as such isn't. | |
| Jan 3, 2022 at 19:52 | comment | added | ilkkachu | @Erhannis, I'm not sure what you mean with "command substitutions are expanded". If you did rm $(cat files.txt), then yes, the shell would expand the command substitution by running the command inside, removing any trailing newlines, word splitting and globbing the result and passing the resulting fields as arguments to rm. But it wouldn't process any quotes on the output. It also wouldn't process any quotes on the result of the *.txt glob. | |
| Jan 3, 2022 at 19:49 | comment | added | Erhannis | @ilkkachu (note, this was in response to the "Don't_stop_me_now" comment, we posted at the same-ish time) I base my "command substitutions are expanded" on experimental evidence: if I type echo *.txt into the console, I get *.txt, but if I type ls $(echo *.txt) into the console, I get a list of filenames. (Based on the rest of the discussion here, I wouldn't expect it to behave properly with e.g. filenames-with-spaces, but it does seem to be expanded, at least.) Is this consistent with what you were saying? | |
| Jan 3, 2022 at 19:49 | comment | added | ilkkachu | @Erhannis, yes, that's how the POSIX shell works. Unquoted expansions are subject to word splitting and globbing, both of which you should usually avoid by quoting the expansion. Or by switching to zsh or some real programming language and using NUL-separated lists of filenames instead of quotes or newline-terminators. No, not all of us love how it is, but that's what a history of keeping compatibility with the past gives you. | |
| Jan 3, 2022 at 19:44 | comment | added | ilkkachu | @Erhannis, hmm, command substitutions are a form of expansion, and the same rules apply. If you have the string Don't_stop_me_now.mp3 in the variable f, then running something like ls $f doesn't go on to process the single quote as a quote character. If it did, it would be impossible to work with arbitrary filenames in the general case, as a filename could also contain double quotes and spaces... | |
| Jan 3, 2022 at 19:43 | comment | added | Erhannis | Since roaima's answer at least gives a functional solution to the problem I was trying to solve, I'll leave this open for a few hours in case anybody has any more wisdom to shed, then otherwise accept roaima's answer. | |
| Jan 3, 2022 at 19:41 | comment | added | Erhannis | @KamilMaciorowski I think this was my primary problem. I expected command substitution to substitute the result back into the original command, and interpret it as though you had typed it there to begin with. Instead it (AFAICT) takes the result, and ONLY considers spaces and glob characters as "special" (notably ignoring quotes). While I really want to go on an angry rant about this, it probably wouldn't accomplish anything. So, thanks for the enlightenment. | |
| Jan 3, 2022 at 19:37 | comment | added | Erhannis | @ilkkachu I see now that they are different things, yes. I'm still not convinced they SHOULD be, but that's sortof irrelevant, I guess. I'm not sure why you bring up "the output of expansions", and FTR it appears that the result of command substitutions are expanded. | |
| Jan 3, 2022 at 19:20 | comment | added | ilkkachu | "Backticks giving different result than pasting result" -- yes, because they're a different thing. Pasting the output on the command line has it go through all of the shell's command line processing, including parsing shell operators, quotes and expansions. Those are not done on the output of expansions, and it's very well so, since otherwise it would be impossible to handle e.g. filenames that contain quotes or something that looks like shell operators. That's also the same as happens in e.g. Perl or any other programming language when e.g. the value of a variable is used. | |
| Jan 3, 2022 at 18:55 | comment | added | Kamil Maciorowski | mv $(find …) … (or equivalent with backticks) is basically as flawed as for f in $(find …); do …, the Bash pitfall number 1. | |
| Jan 3, 2022 at 18:44 | answer | added | Chris Davies | timeline score: 3 | |
| Jan 3, 2022 at 18:37 | history | asked | Erhannis | CC BY-SA 4.0 |