8 ms·
1. It's amazing that they're doing this as a gradual C++ to Rust rewrite, while keeping it working end-to-end, if I understand correctly. 2. It's amazing how q
by cube2222 3y ago
1. It's amazing that they're doing this as a gradual C++ to Rust rewrite, while keeping it working end-to-end, if I understand correctly.
2. It's amazing how quickly this is going.
3. If you haven't tried fish yet, make sure to do so! It's a really ergonomic shell and overall very pleasant to use, with good defaults (you don't have to customize it, even though you can, for a great experience). I've switched from bash a couple years ago and haven't looked back since.
Bonus: you won't have to google how to write a for loop in bash ever again (which I, writing them rarely, and them being unintuitive enough, had to do every single time)!
- shmerl 3y agoTip for some easy to remember Bash loop constructs: Incremental index: for ((i = 0; i < 10; i++)); do echo $i; done For iterating over an array: foo[0]=a foo[1]=b for i in ${foo[@]}; do echo $i; done
- cube2222 3y agoJust to illustrate for others, in fish that would be for i in (seq 10); echo $i; end or usually written as for i in (seq 10) echo $i end and that is already based on iteration, so for iterating over files, you'll similarly use for f in (ls); echo $f; end and it works the same for arrays.
- user982 3y agoYour example in fish: for i in (seq 10); echo $i; end directly translated to bash: for i in $(seq 10); do echo $i; done
- bravetraveler 3y agoNo need for seq :) for i in {1..10}; do echo $i ; done If, for whatever reason, you want leading zeroes - BASH will respect that. Do {01..10}
- shmerl 3y agoseq would work in bash too, but it's not part of the language, it's an external tool. C like syntax is more expressive I'd say for simple numerical increments.
- deleted 3y ago[deleted]
- paradox460 3y agoYou don't even need the (ls) for file iteration: for i in * echo $i end Fish also has globstar out of the box, so you can do for i in **/* echo $i end
- fuzztester 3y ago[You don't even need the (ls) for file iteration: for i in * echo $i end ] You don't even need the for for that (specific example): echo * at least in sh and bash.
- fuzztester 3y agoAlso, IIRC, and less commonly seen, you can do: for i do # your commands using $i here done which will iterate over all the command line arguments to the script containing that for loop. It is a shortcut for: for i in $* # note: not for i in * # the rest is the same above This is mentioned in either the shell man page or in the Kernighan & Pike book The Unix Programming Environment.
- j16sdiz 3y agoecho * does not have the newline after each file
- fuzztester 3y agoTrue, echo * will print all the filenames on one line, with a space between pairs, but for data processing purposes, the two snippets are equivalent, because as per shell behavior, newline, tab and space are all treated as space, unless quoted. Like the definition of whitespace in the K&R C book. After all, Unix is written in C.
- cdrt 3y agoYou wouldn’t iterate over `echo *` anyway. This works just fine in bash/sh: for file in *; do echo "$file" done
- arp242 3y agozsh makes this so much easier. This doesn't capture $i, but covers most use cases of "I want to run something more than once": repeat 10; echo "repeat me" If you do need $i you can use a similar construct as bash, but more convenient: for ((i = 0; i < 10; i++)); echo $i for i in {0..10}; echo $i # {n..m} loops also work in bash for ((i = 0; i < 10; i++)); { echo $i; echo $i } # Multiple commands Short loops are hugely helpful in interactive use because it's much less muckery for short one-liners (whether you should use them in scripts is probably a bit more controversial). Also looping over arrays "just works" as you would expect without requiring special incantations: arr=(a b) for v in $arr; echo $v --- Whether zsh or fish is better is a matter of taste, and arguably zsh has too many features, but IMHO bash is absolutely stuck as a "1989 ksh clone" (in more ways than one; it uses K&R C all over the place, still has asm hacks to make it run on 1980s versions of Xenix, and things like that).
- JNRowe 3y agoAny reason to eschew short_loops in general that you're aware of? I ask because I'd probably use `for i ({0..9}) echo $i` in your for loop example. I've never managed to get my head around the necessity for a narrow short_repeat option when there is - for example - no short_select. All of the zsh alternate forms feel far superior to me, in both interactive use and within scripts. JNRowe notes the many off-by-one translations in other examples and tips hat to arp242
- arp242 3y agoOh yeah, I forgot about the {n..m} syntax; I almost always use repeat these days or the C-style loop if I need $i, as that's more "in the fingers", so to speak, from other languages, even though {n..m} is easier. I don't know why you would want to avoid short loops, other than subjective stylistic reasons (which is completely valid of course). The patch that added short_repeat just asserts that "SHORT_LOOPS is bad"[1], but I don't now why the author thinks that. Also: my previous comment was wrong; you don't need "setopt short_repeat"; you only need it if you explicitly turned off short loops with "setopt no_short_loops". [1]: https://www.zsh.org/mla/workers/2019/msg01174.html https://www.zsh.org/mla/workers/2019/msg01174.html
- darrenf 3y agoFor the first, I prefer range syntax: for i in {1..10}
- stouset 3y agoPlease please please always quote variable expansion. Just do it everywhere, every time. for i in “${foo[@]}”; do
- pjot 3y agoTo illustrate why, consider a file name with spaces. filename="my file.txt" cat $filename # Incorrect: Tries to 'cat' two files: 'my' and 'file.txt' cat "$filename" # Correct: Treats 'my file.txt' as one file
- mgdlbp 3y agoAdditionally, $ f=-x $ cat "$f" cat: invalid option -- 'x' $ cat -- "$f" cat: -x: No such file or directory # ^-- correct, but: $ f=- $ cat -- "$f" reading stdin... reading stdin... ^C $ f=./- $ cat -- "$f" cat: ./-: No such file or directory ...better to glob with ./* than *
- pjot 3y agoAlso for sanitizing user input. input=$1 # User input, potentially dangerous rm $input # Incorrect: Risky if input contains something like '*' rm "$input" # Correct: Safer, treats the user input as a single item
- akho 3y agoOr use Fish.
- madeofpalk 3y ago“Just remember how to do it” isn’t really the problem. It’s that the finer details of the syntax is sufficiently different from other things I do, and I don’t write shell scripts frequently enough to remember it.
- doubloon 3y agoexactly. i predict some kind of 'chat gpt shell' in the near future.
- cube2222 3y agoGitHub has already released this a couple months ago: https://docs.github.com/en/copilot/github-copilot-in-the-cli/using-github-copilot-in-the-cli https://docs.github.com/en/copilot/github-copilot-in-the-cli...
- deleted 3y ago[deleted]
- mgdlbp 3y agozsh, short loop: for i in {1..10}; <<<$i powershell: foreach ($i in 1..10) { $i } 1..10|%{$_}
- deleted 3y ago[deleted]
- xorcist 3y ago> For iterating over an array: Bash array syntax is error prone and hard to read, and the expansion of arrays still depend on the field separator and must fit in the environment. Most of the time you should just rely on that field separator and do it the simple way: for i in "$f"; do echo $i; done Much more obvious and more shell-like. That's how all bash functions process their parameters. Set IFS only if you really need to. But in that case also consider something like xargs where you are not limited by environment, have null terminated fields, and offer parallelism. Arrays are only useful when you need multidimensionality, at which point you should probably look at using data files and process with other tools such as sed. Or start looking at something like Perl or Python.
- cdrt 3y agoYour example proves that not using arrays is worse. That loop will only run once and just print every element on one line. The array equivalent works as expected , _isn't_ affected by IFS, and can handle spaces in individual elements f='a b c d e' for i in "$f"; do echo $i; done # prints a b c d e f="a b c 'd e'" for i in $f; do echo $i; done # prints # a # b # c # 'd # e' f=(a b c 'd e') for i in "${f[@]}"; do echo $i; done # prints # a # b # c # d e
- xorcist 3y agoYou could always construct an example to how a specific behaviour. The problem in the example here is that you can't set environment variables to a list of arguments, you can only set it to text strings. Normally on the command line data comes from somewhere. It might be some sort of text processing such as a grep or sed command. And that works just fine: for i in "$(grep stuff)"; do works just fine and as expected. But when you have to slice and dice that output to fit bash arrays, you not only have to take IFS into account, it quickly gets way harder to read than doing it the normal way. That's why I generally tend to view the use of arrays as a warning. Maybe you are doing something unnecessarily complicated, maybe you are writing Python in bash. Your specific example should be written as the easiest form: for i in a b c "d e"; do echo $i; done which does precisely what it looks like.
- benj111 3y agoCan't speak for others but one issue is the "; do" I can generally cobble together python, and it'll be syntactically correct. I just need to check libs. With shell I need to stop and make sure my semicolons in a for loop are correct. If you're a heavy user it probably isn't a problem but all the little warts just make it difficult for an occasional user to keep a good enough model in their head.
- andrewshadura 3y agoYou don't need the semicolon. Just use a newline instead; it's also easier to remember that way.
- capableweb 3y ago> 1. It's amazing that they're doing this as a gradual C++ to Rust rewrite, while keeping it working end-to-end, if I understand correctly. Seems to me they're not doing it gradually at all. > Another thing: > We plan on not doing any partial-rust release. > That means we would be doing e.g. fish 4.0 as fully rust and zero C++, and I think, contrary to what we usually do that warrants a beta. (Ordinarily we've stopped doing betas and release candidates because they simply don't get any testing). > We also still want to do a 3.7.0 in-between release that is still purely C++, so we have a better jumping off point for platforms that can't handle the rust version. It would be 3.6.1 with some neat changes backported. https://github.com/fish-shell/fish-shell/discussions/10123#discussioncomment-7672965 https://github.com/fish-shell/fish-shell/discussions/10123#d...
- Cu3PO42 3y agoIt's a bit of both. They are not doing any mixed C++/Rust releases, but you can check out the source and build it in the current mixed state and it will produce a binary that contains parts from both languages and works as a Fish shell.
- Animats 3y agoThe price of C++ compatibility is that it doesn't use Rust strings internally. It's all "wchar" and "WString", which are Microsoft C++ "wide character strings". This may be more of a Microsoft backwards compatibility issue than a C++ issue.
- giancarlostoro 3y agoI still rather write Bash scripts or just bust out Python or Perl, but I definitely prefer Fish for terminal usage.