[kwlug-disc] fish vs bash: a progress bar from YSAP and some timing measurements

Doug Moen doug at moens.org
Sun Aug 24 07:27:59 EDT 2025


The fish shell focuses on having a really great interactive experience. As a programming language, it seems to be meh. It has the concept of a list of strings, but lists cannot be nested. When you call a function, you pass a list of all the function arguments: this is $argv. It's impossible for the first argument, $argv[1], to be a list, because lists cannot be nested. Looking at the fish documentation, I might avoid using 'function -a' because it doesn't look particularly well thought out.

If you want a shell that focuses on being a really great programming language, then you can look at YSH from the OILS project. In that shell, you can manipulate arbitrary JSON data structures, so nested lists are not a problem. If you want to write shell scripts and define functions, YSH is much much better than Fish. For example, you would write if (x < y) instead of if [ $x -lt $y ].
https://oils.pub/release/latest/doc/ysh-tour.html

OILS also has OSH, which aims to be BASH compatible while fixing a huge number of bugs, and tab completion is also said to be better. AFAIK tab completion in YSH shares code with OSH and is also supposed to be better than bash, but I haven't tried it.

Doug.

On Sat, Aug 23, 2025, at 11:56 PM, Ron wrote:
> Ron wrote on 2025-08-23 00:28:
>
>> The fish syntax is *so much better*.
>
> I'm reminded of how nginx came along and really took a lot of install 
> base from Apache.
>
> Is it because it's faster? Maybe; debatable on equivalent work loads 
> (from my understanding).
>
>
> Is it because the configuration syntax is much cleaner, clearer, 
> legible, and sane?
>
> I think so.
>
>
>
> One quirk I've encountered is in passing an array to a function and 
> accessing it as a variable. This may be due to a failure to understand 
> something on my part, but I don't think so.
>
>
> Functions are defined something like this (formatting for personal 
> preference only):
>
> ```
> #!/usr/bin/env fish
>
> function myfunc                                            
> --description "This appears in tab-completion hints"     -a my_arr
>
>    echo -e "Inside myfunc \$my_arr has $(count $my_arr) item:
>  $my_arr"
>    echo -e "Inside myfunc \$argv has $(count $argv) items:"
>
>    set -l i 1
>    for arg in $argv
>      echo "  $i/$(count $argv): \$argv[$i]: $argv[$i] (or \$arg: $arg)"
>      set i (math $i + 1)
>    end
>    ## printf "myfunc argv passed: %s
> " $argv
> end
>
> ## In bash, ** requires `shopt -s globstar`
> ## and `shopt -s nullglob` lest one gets either the string "./**/*.cache"
> ## if no matches or something else unwanted (I forget)
> set files (ls ./**/*.cache)
> echo "Found $(count $files) files in a test array"
> ## Indexing starts at 1 (yay!):
> myfunc $files[1..5]
>
>   $ ./test2.fish
> Found 500 files in a test array
> Inside myfunc $my_arr has 1 item:
>   ./baz/delme-100.cache
> Inside myfunc $argv has 5 items:
>    1/5: $argv[1]: ./baz/delme-100.cache (or $arg: ./baz/delme-100.cache)
>    2/5: $argv[2]: ./baz/delme-101.cache (or $arg: ./baz/delme-101.cache)
>    3/5: $argv[3]: ./baz/delme-102.cache (or $arg: ./baz/delme-102.cache)
>    4/5: $argv[4]: ./baz/delme-103.cache (or $arg: ./baz/delme-103.cache)
>    5/5: $argv[5]: ./baz/delme-104.cache (or $arg: ./baz/delme-104.cache)
> ❰uid1❙~/utils/ysap-bash/progress-bar❱ ✔ ≻
> ```
>
> So, passing in an array and capturing the entire array in a local 
> variable does not (seem to) work.
>
> However, that array is accessible as $argv, so ... that's okay.
>
>
> I do like that indexing starts at 1 - that's great!
>
>
> _______________________________________________
> kwlug-disc mailing list
> To unsubscribe, send an email to kwlug-disc-leave at kwlug.org
> with the subject "unsubscribe", or email
> kwlug-disc-owner at kwlug.org to contact a human being.


More information about the kwlug-disc mailing list