I love fish shell, I love the autocomplete, but I've been forced to switch back to bash lately, because fish syntax is just different enough from bash-isms to break too much scripts / tools / commands.
I know I could just invoke bash, but prefixing commands with "bash -c '" is tiring and papercuts are why I switched to fish in the first place. I wish bash had a sane auto-complete prediction like fish.
Your scripts should begin with #!/bin/bash or similar so you can execute them from anywhere. Are there bash built-in commands or functions that you need while in fish?
There's some initial pain in retrofitting your Bash startup to work under fish, but after that it's worth it. For example I had to search for how to use ssh-agent with fish, and now it works great: https://github.com/st3fan/dotfiles/blob/master/fish/ssh.fish
You need to learn a few idioms like: replace $[1+1] with (math "1+1"); replace
> for f in $(ls); do echo $f; done
with
> for f in (ls); echo $f; end
I should start a Rosetta Stone of Bashisms to Fishisms - I'd be interested if anyone has got Android Open Source build environment / lunch working.
bash uses readline to handle user input and in readline the completion function is a parameter. Could a more clever completion function be substituted to get the same behaviour with bash?
You can get it much of the way there by tweaking `~/.inputrc`
"\e[A": history-search-backward # Up key
"\e[B": history-search-forward # Down key.
Allows you to get press up while you have `ssh 10.2` in the terminal to cycle through ips matching, etc. It won't display like in fish before pressing it, but I find that's a reasonable tradeoff.
If nothing else, I have thousands of lines of my own shell scripts that I don't care to move to a different shell syntax that's not obviously better :)
There are lots of posts on the blog about it, but here is an example:
However one thing is that it's not yet a good interactive shell. It's mainly treating bash as a programming language. However I think that is a good foundation for an interactive shell. Some details here:
Fish is really great for using it in your terminal. Autocompletion, fuzzy matching, and so on, are amazing.
Unfortunately, although it is fully scriptable, writing scripts in Fish feels a little clunky at times. For example, I wanted to test if $dest exists, and if not, whether $src is newer than $dest. Since there are no && or ||, parentheses are used for command substitution, and the Fish version of "test" has no -nt to check if a file is newer, I have to do this:
if begin; not command test -f $dest; end; or begin; command test $src -nt $dest; end
# do something
end
I'm a very happy fish user but this is one of my pain points as well. If you want to define a function, the syntax is light-years ahead of bash, including named arguments (and closures!), but it took a fair bit of googling and eyebrow-wrinkling before I could figure out the way just to set a default argument for that function.
What I ended up with was (for a shortcut for generating a password on the command line):
function pw --argument length
test -z $length; and set length 16
python3.6 -c "import secrets; print(secrets.token_urlsafe($length))"
end
It's true fish is generally more verbose, as it has less magical syntax. fish is also missing some niceties like `set -e` and `set -x` which we would like to add, but the main focus is interactive use.
Happily the begin/ends in ifs are no longer necessary:
if not command test -f $dest
or command test $src -nt $dest
# stuff
end
In this particular case, you can simplify it further with test's operators:
if command [ ! -f $dest -o $src -nt $dest ]
#stuff
end
which is comparable in length to bash, though other cases will certainly be longer.
I think you should actually use "; and" in place of &&. That said I still wish fish support && and ||, if only for the times when I copy and paste some one-liner off of stack overflow and have to rewrite it.
I’ve been enjoying fish for the handy tab complete of command line options, the interactive history, and it’s pretty.
I’m certainly guilty of finding one-liners online which frequently fail in fish, which puts me in the position of either actually learning what the terse statement actually does and re-implementing it in the fish “c-like” syntax, or I just drop into bash then get on with my business.
Really happy with it, but I know I get sideways stares from graybeards and gurus who consider it the small-batch, fixed-gear, “Crocs” of shells.
Correction: Most bash scripts are brittle. You can write rock-solid bash scripts if you know what you're doing. For example, Arch Linux is an entire distribution built mostly on bash scripts.
Of course, if your scripts only run on your own machine (which is a huge if), then fish is probably better.
Sure you probably can write non-brittle bash script, but it has always seemed above my own ability.
Beyond bash ubiquity, I've never found to have any other value against other slightly higher language whether it is perl, tcl, python, etc ...
Not GP, but since 90% of of my sporadic scripting is "searching on SO how to do something somewhat complicated that I'll never do again so it's not worth the time to learn how to master it", bash is (oddly enough) a lot easier to use here since looking up how to do it in Fish is a lot more hassle.
Similarly, if you want your code to be portable, bash is a safer bet.
I put that badly. Fish certainly does support scripting, but as a relatively niche piece of software you get bad portability (everything has bash) and poor maintainability (because everyone else scripts in bash). Fish is a great shell and maybe this will change, but at the present time I'd be doing my clients a disservice if I wrote them tools in a language few others could work with.
I find fish to be a more pleasant scripting languge personally, but bash scripts are the lingua franca everywhere I've worked. It's easier just to learn bash.
I wouldn't use it because I wouldn't want to add a somewhat strange and unnecessary dependency to my projects. It's also why I resist switching from bash even though I've used other shells and enjoyed them. There are only so many skills I can keep in good practice. If I use bash then it will be one of them.
That is the one thing I really didn't like about Fish; that and how the help screens use to launch in a web browser. But once you get past the initial configuration, you never use that stuff again. Despite that fault, I still love Fish shell.
The web based configuration is completely optional. Editing dotfiles works just as well. I have been using fish for quite a while but never use the web interface (I didn't even remember it existed)
I've been using fish for 3 ~ 4 years and I love it. It's come a long was in its development and it's interesting to watch as so many of the bugs have been resolved. Today's fish is incredibly stable and solid. The history, highlighting and completion are well beyond what I've seen in other shells (at least not without adding additional plugins).
I still write scripts in bash for compatibility (when I have to; I try to use Python whenever it's an option), but for my interactive shell, fish is really amazing and I'd hate to go back to anything else.
I've been using fish for a few years now, and it has made bash feel not just outdated, but completely obsolete. I am at loss for why it hasn't taken the entire world by storm.
Of course I think my own project, Oil, could be a "21st century shell", or I wouldn't be working on it :) It's designed in a principled way, and it's also the only one that's compatible with bash.
I used fish twice for about a year each time, but I keep switching back to zsh, because:
* The main things I like about fish are predictive history completion and syntax highlighting, both of which work about the same with a pair of zsh plugins;
* The syntax occupies what is, for me, an awkward middle ground: it's a bit better than POSIX syntax if POSIX shells didn't exist, but not enough better that I care to juggle the two syntaxes;
* I don't like that fish tries to be "helpful" in certain cases such as lying to you about the delimeter actually used by $PATH.
I have a couple of specific gripes about the syntax, which aren't really inherent issues so much as unimplemented features.
I think if I was going to deviate from a POSIX shell, the alternative would have to be more better than fish to be worth it.
There's nothing major. I maintain a set of POSIX and fish scripts as part of my job and, given that I have to know both relatively well, I find I end up preferring the on-average-slightly-more-terse POSIX syntax.
One thing that can be particularly annoying is that it seems to be impossible in fish to evaluate a command in a subshell and embed its output into a string without assigning it to a variable first.
ARGV handling is a little weird too. I understand the impulse to get rid of $1, $2, $3, $*, $@, $#, etc., but it ends up just requiring different gymnastics, like writing `set -e argv[1]` instead of `shift.
> Out of curiosity, what use case do you have that makes a POSIX shell a big deal?
Running on a POSIX system, there are decades' worth of shell snippets out there which don't work with fish, but do with sh, ksh, bash & zsh.
Fish is just gratuitously incompatible. Having fish-users on a team is a pain, because they'll write everything in fish and either not bother producing sh equivalents, or produce insufficiently-tested sh equivalents. It's just a lot of pain and bother, and what's the benefit? Zsh does everything fish does and more, so why not just use it?
Edit: I just wish that the original fish developers had chosen to implement all their cool features and be sh-compatible, or at the very least had exercised some wisdom in where they chose to break compatibility. Instead, it very much feels like a 22-year-old's project: full of ideas, some good & some bad, and needlessly without respect for the past. I've no problem with rejecting the past when the past is broken (and sh is broken in places); my problem is with the equivalent of saying, 'hey, English spelling is terrible, soh Aiv dəseidid tū dəvelup mai ohn.'
Back in the day I used to use csh and tcsh, both of which had famously landmine-laden scripting gotchas. So, I wrote my scripts in sh or bash. Now that I use zsh mostly, same thing, I don't actually write my scripts in zsh--especially for production, I write them in sh or bash. zsh for me is an interactive CLI-only tool. Honestly, I think the problem here sounds more about not standardizing on a common denominator for shared scripts.
Where stuff like fish is a pain for me is with apps that for whatever reason need shell integration (virtualenv, for example). Non-POSIX shells end up being an afterthought there, so you end up with no or buggy support, and end up having to find some other custom variant (virtualfish, etc.) to get good behavior. Sticking with a more mainstream shell tends to be safer there, and zsh barely makes it over that line.
I started with bash, moved on to zsh and finally settled on fish. Besides fish being super user-friendly out of the box, I couldn’t find a zsh plugin that emulated its history search abilities.
There are two history search features in fish that I really like: One is searching for a half typed command as above, but the other one that I haven’t found elsewhere is completing words from other commands. For example, I can type ‘touch something’ and later on do ‘cat some’ and then press option+up and fish will complete it to ‘something’.
After using ZSH I have that first feature and love it. I try to keep as much of my history as possible and it's amazing how much time you can save that way. Does that second feature not clutter up that history though?
Is it possible to configure zsh to have sane variable expansion like fish does? One of my favourite parts of fish is that I don't need to quote every variable I use out of a paranoid fear that they might contain spaces.
> * The syntax occupies what is, for me, an awkward middle ground: it's a bit better than POSIX syntax if POSIX shells didn't exist, but not enough better that I care to juggle the two syntaxes;
This. It's an awesome shell, but I couldn't set is as a default because my already done shellscripts and aliases would stop working. And I also can't set it on server, because then a deployment tool logs in, and expects bash.
And if it isn't default, I might not bother, I'd forget to run it manually most of the time.
(The worst offender is replacing && with 'and' - why not at least enable both and preserve compatibility?)
It is also worth noting that the ecosystem around fish is quite developed, making it easy to get easy integration and completions for most well-known tools.
oh-my-fish [1] plugins is a good place to see (part of) what is available
Hey all, one of the fish devs here. It's awesome to see all of the comments and happy users.
We are in the process of scoping a major release (fish 3.0) that can include major syntactic changes. If there's an aspect of fish you would like to see changed, now is a great time! Of course we'll read the comments here, and our issues page [1] is where discussion happens.
We're also welcoming new contributors. It's easy to get started writing completions or with the issues labelled "easy-pick". The core code base is reasonably modern C++ too.
I implore you to NOT use JSON or ProtocolBuffers, neither are appropriate formats for configuring my shell, or storing long sets of textual data. Protocol Buffers is hardly the kind of format I want to parse and read my history in, and JSON is a less than ideal configuration format for many reasons.
https://github.com/vstakhov/libucl UCL (Universal Configuration Language) is a much more appropriate format for configuring programs than JSON, and is has been accepted as standard for use configuring all tools included in the FreeBSD operating system.
I also suggest you consider using a different language to store shell history, since shell history and shell configuration are two very different jobs with different goals and trade offs. I personally would suggest a simple safe format like TOML https://github.com/toml-lang/toml for storing the history.
But If you do want a single format for both configuration and history, I would implore you to pick TOML not JSON or Protocol Buffers.
Thanks for writing that up, I linked to it from the issue. FWIW I agree with you that shell history should be a simple format, and even ad-hoc parseable via Unix tools. zsh uses simple : and ; delimiters. JSON is more complex, and binary formats like protobuf are way out.
Out of the mainstream formats, JSON is among the easiest to parse - thanks to the CLI tool jq. Does UCL have something equivalent?
Protobuf (or any other binary format) has the benefit of being faster to load, but I agree - it should not be be used to store things like history. It should be easy to parse history without having to write code. And with Protobuf, you need the schema.
If a binary format is going to be used, it should be optional - or perhaps there should be tools to convert the history file to/from a plaintext format.
There is uclcmd [https://github.com/allanjude/uclcmd] which could do with some more work but was created with the intent of being a UCL equivalent of JQ.
Supporting this, I don't think protobuf is a good format for storing history files. Backward compatibility is tricky with it - I don't think the history format is going to change all that much, but I think there were changes in history of fish shell like adding time field. If the choice would be on a binary format, I would much, much, much more prefer SQLite for that. Also, B-trees are perfectly fine choice for searching history, as they make prefix searches trivial.
TOML is definitely an interesting choice if a text format is deemed necessary however. Array of tables syntax should be a fine syntax choice for storing history.
In addition protobuf is designed for communications, not incremental updates in a local store. As such making things robust to store things on a development machine is non-trivial. SQLite is so much better for that. After Firefox switched to use it for its own history, most problems with history corruption disappeared.
I was about to say SQLite, it seems perfect - binary, fast, easy to update cheaply in place, immune to escaping et al problems (if you use prepared statements, not glue SQL with + of course), reliable, available in most languages (even for C and C++ the integration is trivial - it's a single pair of files drop in) and on the CLI, stable, the history data is very row/item oriented and not totally heterogeneous or free form, etc.
I totally drank the SQLite koolaid a long time ago.
History file may be read & updated simultaneously my multiple processes. Is that sufficiently safe from corruption with SQLite?
(honest question, no FUD implied. same risks apply to alternatives too.)
For configuration I would very much prefer to have something that can be properly grepped/patched/generated with shell scripts if necessary. What openssh uses for its config mostly fulfill this, but ini file also are not that bad. Anything hierarchical like JSON/TOML/UCL etc. becomes very unattractive the moment one has to patch them from automated setup scripts.
Both are single binaries, so easy to run them where you need it. I don't know comparable stuff for the other mentioned formats, whenever I need to deal with yaml in scripts i run
I would be totally fine with any format that can be converted to JSON on the fly. Of course I would love to have something like these tools more integrated within a shell, but the representing text format on the disk is not that important for me.
Long-time fish user here, I'll second this comment and implore that you choose TOML for the configuration format. TOML format is easy for users to understand, and well-written parsers for it exist in every programming language.
We're open to a lot of things (except "make it fully POSIX-compatible"). We're still trying to not massively break everything, though.
The sort of things we've discussed include:
- Not expanding `{}` so you don't need to quote it with e.g. `find -exec {}` (currently this is read as a zero-element brace expansion, i.e. it expands to no argument)
- Removing the `?` single-character glob because it's apparently entirely unused and is another special character to remember (in fact we've also talked about removing `^` as a shorthand for redirecting stderr and `%something` process expansion)
- Allowing `$(command)` command substitutions, which could be used inside quotes as well (long term, these would replace our current `(command)` style)
- Possibly removing the special handling we have for $PATH, $CDPATH and $MANPATH (these are treated by fish as lists, which is nice in some ways and causes pain in others)
pgcli was a huge help to some former colleagues who had some trouble working with relational databases and SQL for the first time. I'm a big fan myself as well. Thank you for building a great piece of software.
Avid fish user since last 3 years. On feature I miss from bash is the `sudo !` to re-run previous command as sudo. Last time I checked fish didn't offer an equivalent. Either that or something similar will be useful
In fish Alt+Up does something similar, but repeated presses iterates over all words of all commands rather than last words of bash commands. A big improvement is you can type some chars first and then Alt+Up only gets words matching this substring — like Up but word granularity! (Closest bash key is Ctrl+Alt+I)
If you don't mind the differences, and want Alt+. muscle memory to work in fish too, do:
bind \e. history-token-search-backward
(plus Alt+Up doesn't work for me in linux console, Alt+. does)
If there is anything I would personally like to see it’s the bass plugin rolled into the shell itself to make transitions for bash and some esoteric edge cases easier to handle https://github.com/edc/bass
While I like fish, I stopped using it because of a small convenience feature ZSH has.
With ZSH, I can run a command with a space at the start so it's excluded from history, even though its not saved to disk, the last command is still stored in memory so I can press Up to access it again.
This is handy when a mistake is made in the command means I need to run it again with some small change.
This feature seems to exist also in bash. I discovered it accidentally while wondering why my history did not include my last commands (copy/pasted with a leading space).
Heh I have the opposite preference, I use space to ensure when pressing up it will not bring up that command, to not mistakingly run it when muscle memory will expect another command there (for mv and rm commands mostly)
Hey, thank you for contributing to one of my favorite pieces of software :) The Fish shell is my primary choice, because it's so intuitive and easy to use. I never encountered a situation where the Fish shell behaved contrary to my expectations. I do wish there was a native Windows version, because that's where I spend 50% of my digital time, but only because it's so great.
I tried fish and it seemed ok, I didn’t continue with it cause I needed to rewrite all my aliases and functions (work related not at home). From memory one was && vs “and” which we use a lot to chain commands. Something like implementing &&/|| would go a long way, compat command sub, closing if statements . I know it seems like a small thing to modify your aliases/functions but I would basically need to modify mine and be a maintainer for the shared ones.
TLDR adddition transitionally compat with bash or zsh
I would love to see zsh navigation tools[0] be integrated in fish. There is a long standing issue in fish which is the support for CTRL-R history, while many are pondering on the UI of it. I would like to see znt's UI be adopted (not saying it's perfect, but quite a good starting point for user conversion).
Copy and pasted from another reply: "I still wish fish support && and ||, if only for the times when I copy and paste some one-liner off of stack overflow and have to rewrite it."
That and support for
SOME_ENV_VAR=foo ./bar
(not having to prepend "env ") are what's stopping me from recommending fish to others.
I really like that you have to use `env` in fish, since it's cross-shell - it works in bash/zsh/dash/whatever. The `A=b foo` syntax is an unnecessary appendix in the syntax that complicates matters while only saving 4 characters.
I agree and think the best fix would be if the syntax would be forbidden in bash/zsh. Problem is: Millions of code snippets on the Internet not using env.
That syntax is from very early days of sh itself (predecessor of bash), IIRC. So removing it would break many scripts, as sibling comment by jhasse said.
It's not just to save typing - having an `A=b foo` form built-in instead of relying on an external program means `foo` can be an alias or shell function.
Vi mode has been implemented since 2.2.0 (July 2015), although it's an ongoing work in progress - if there's something missing then we'd consider adding it (although nobody's going to reimplement Vim in fish - sometimes Alt-E is your best option).
I'm very glad to see that getting rid of the magic path variable semantics is a possibility for 3.0 :)
Other than that, my biggest pain point with fish now is that it doesn't interact well with pkg-config (issue #982) and the workarounds for that are a bit awkward. eval is scary and may require double-quoting the non-pkg-config parameters, and string splitting can wrongly split inside quoted text.
It would be great if Fish supported &&. I know it has its own syntax for this but it's not particularly fun going through a command you copy pasted from elsewhere and swapping out all the &&s (I usually just end up firing up bash).
Fish's FAQ already explains why it doesn't use `!!` – it says that editing commands from history by pressing the up arrow is more memorable and flexible. I don't find it a problem to type “up Ctrl-A sudo” instead of “sudo !!”.
the main feature i use fish for is the syntax expansion, and history usage of it.
The biggest gripe i have with it is the specific syntax. If fish would act more like a bash shell in case of syntax. ( i know i would need a totally different shell). But it could replace the fish for me in an instant. everywhere.
Anyways.
Thanks for the fish.
Thanks for it! I am also using Fish happily for interactive terminal work. Not so much for scripting as I am lazy to learn the new syntax.
What I don't like is that after hitting Tab twice when doing path completion, the list of possibilities comes out, allowing arrow keys to be used for selection. The problem is that it requires pressing Enter to confirm the suggestion and I fear of executing the command with incomplete path prematurely (it's just one more Enter hit away).
It's a Python-based shell that attempts to be somewhat bash-compatible (for ease of use over, e.g., IPython). Instead of making a new scripting language (fish), go all in.
Pros: scripting is amazing.
( while True: ls ~ )
Cons: can be a bit slow (because Python interpreter).
I definitely prefer zsh. I just feel like Fish tries too hard and it's just awkward to switch between fish and bash when frequently switching between different machines.
Loved it a few years ago, stopped using it when I started using conda and it didn’t support switching into those environments. I’ll try again hopefully that’s fixed.
The great thing about fish for me is that comes so nicely set up on first install that, a few path additions aside, I don’t have to mess with it. Any time spent on shell configuration is time wasted from my perspective.
This in turn means I’m willing to install it with no hesitation in all my local and remote logins, so I have a uniform simple setup everywhere.
I've used fish as my shell for over five years. Thanks to the developers!
One issue is the behavior of globs. I often want to do "scp host:directory/* ." but you can't do that in fish, so I drop to bash. That's pretty much all I drop to bash for.
Note that the reason bash works here is actually a bit ugly.
Like fish, it'll interpret an unquoted asterisk (sorry HN formatting) as the glob character. So it tries to match pathnames to `host:directory/`.
Only the default bash behavior (if "nullglob" and "failglob" aren't set) is to pass the literal glob expression if no match could be found.
So once you `mkdir host:directory; touch host:directory/file` (which you can do - this is unix, so almost all pathnames are allowed), this will be broken.
This means you _should quote the token_ in bash, which is exactly what you should do in fish.
Note: This is also why you might see code like the following in bash:
If you like fish but miss the plugin ecosystem of zsh you might be interested in the fish-shell plugin manager, fisherman. I've really been enjoying fish with z and fzf.
I've been quiet happy with https://github.com/junegunn/fzf/wiki/Examples-(fish) as a ctrl-r replacement for fish. I would love this included natively in fish though so I won't have to manage remote shell configurations.
No, not to my knowledge! It does autoindent things for you when you’re editing multiline functions inline, but whitespace is fortunately not significant.
Love fish, especially because of the easy configuration and out of the box features. No need for complicated frameworks or curated dotfiles. There are two syntax changes I’d love to see:
1. Support for last command by !!, as in `sudo !!`.
2. Ability to search history from a partial command like `git checkout`, where up arrow would step backward from the present.
That's true. Sorry for my poorly-worded English. For a small example:
$ ls -la foo
$ ls -la bar
$ ls -la /
When I type `ls -l` and hit the up arrow, my first result is `ls -la bar` not `ls -la /`. This is a small problem but sometimes annoying, especially after using other shells that work differently.
In this case, what most likely happens is that the first result is offered as the suggestion - i.e. the greyed-out part in the commandline. To accept that, press right-arrow (with the default bindings, of course).
I use fish as my primary shell. I've ran into a few issues where it broke existing fish scripts, and, uh, let's just say some of the developers (not 'ridiculous_fish) were less than stellar in their response. (I get it. It's open source. You don't owe anyone anything: but you also don't have to be a jerk about it, and I also don't owe you using your software.)
My original reason for using fish was onboarding junior engineers. I had a pretty fancy zsh/emacs setup, and they'd ask me how to make their shell do that (reminder: on macOS you get bash3.2 by default!). So I switched to fish/spacemacs, so the answer isn't "uh sure you can rsync 50MB of accrued elisp".
Still easy to reproduce. Maybe consider some of those plugins. You don't have to give up being POSIXy. Whether or not that's good or bad, I leave up to you :)
(Commented out bits are things I'm playing with: mostly to improve shell startup time.)
212 comments
[ 2.9 ms ] story [ 246 ms ] threadI know I could just invoke bash, but prefixing commands with "bash -c '" is tiring and papercuts are why I switched to fish in the first place. I wish bash had a sane auto-complete prediction like fish.
I use fish interactively and write very simple scripts in bash and the more complex in Python.
You need to learn a few idioms like: replace $[1+1] with (math "1+1"); replace
> for f in $(ls); do echo $f; done
with
> for f in (ls); echo $f; end
I should start a Rosetta Stone of Bashisms to Fishisms - I'd be interested if anyone has got Android Open Source build environment / lunch working.
https://github.com/robbyrussell/oh-my-zsh
"\e[A": history-search-backward # Up key
"\e[B": history-search-forward # Down key.
Allows you to get press up while you have `ssh 10.2` in the terminal to cycle through ips matching, etc. It won't display like in fish before pressing it, but I find that's a reasonable tradeoff.
http://www.oilshell.org/blog/
If nothing else, I have thousands of lines of my own shell scripts that I don't care to move to a different shell syntax that's not obviously better :)
There are lots of posts on the blog about it, but here is an example:
"OSH Runs Real Shell Programs" - http://www.oilshell.org/blog/2017/07/02.html
Another comment: https://news.ycombinator.com/item?id=15916470
However one thing is that it's not yet a good interactive shell. It's mainly treating bash as a programming language. However I think that is a good foundation for an interactive shell. Some details here:
https://www.reddit.com/r/commandline/comments/7c3f9f/osh_02_...
[1] https://github.com/edc/bass
Unfortunately, although it is fully scriptable, writing scripts in Fish feels a little clunky at times. For example, I wanted to test if $dest exists, and if not, whether $src is newer than $dest. Since there are no && or ||, parentheses are used for command substitution, and the Fish version of "test" has no -nt to check if a file is newer, I have to do this:
What I ended up with was (for a shortcut for generating a password on the command line):
Happily the begin/ends in ifs are no longer necessary:
In this particular case, you can simplify it further with test's operators: which is comparable in length to bash, though other cases will certainly be longer.I’m certainly guilty of finding one-liners online which frequently fail in fish, which puts me in the position of either actually learning what the terse statement actually does and re-implementing it in the fish “c-like” syntax, or I just drop into bash then get on with my business.
Really happy with it, but I know I get sideways stares from graybeards and gurus who consider it the small-batch, fixed-gear, “Crocs” of shells.
Good points:
* Fish's completion sure saves a lot of typing
* `brew install fish` on osx
* Config in ~/.config/ rather than cluttering up the root of your homedir
* Can change many settings without needing to edit config directly - eg. `set -U fish_user_paths $fish_user_paths ~/path/name`
Bad / not intended for:
* It's not for scripting. Just use bash for that.
* I've found appending to env vars to be fiddly. Maybe I'm doing it wrong
* pyvenv's bin/activate.fish was broken for a long time (not fish's fault!)
Of course, if your scripts only run on your own machine (which is a huge if), then fish is probably better.
Similarly, if you want your code to be portable, bash is a safer bet.
2) list.reverse(macOS, Linux, and the rest of the family)
I still write scripts in bash for compatibility (when I have to; I try to use Python whenever it's an option), but for my interactive shell, fish is really amazing and I'd hate to go back to anything else.
I'm not so sold on some of the tokenizing / etc styling, but `cat image.jpg` -> see an image? yes please.
Alternatively, I keep checking in on Xiki periodically, since it has some extremely interesting features: http://xiki.org/
[1] https://github.com/railsware/upterm
https://github.com/oilshell/oil/wiki/ExternalResources
Of course I think my own project, Oil, could be a "21st century shell", or I wouldn't be working on it :) It's designed in a principled way, and it's also the only one that's compatible with bash.
* The main things I like about fish are predictive history completion and syntax highlighting, both of which work about the same with a pair of zsh plugins;
* The syntax occupies what is, for me, an awkward middle ground: it's a bit better than POSIX syntax if POSIX shells didn't exist, but not enough better that I care to juggle the two syntaxes;
* I don't like that fish tries to be "helpful" in certain cases such as lying to you about the delimeter actually used by $PATH.
I have a couple of specific gripes about the syntax, which aren't really inherent issues so much as unimplemented features.
I think if I was going to deviate from a POSIX shell, the alternative would have to be more better than fish to be worth it.
I’ve never had issues as a somewhat heavy user.
One thing that can be particularly annoying is that it seems to be impossible in fish to evaluate a command in a subshell and embed its output into a string without assigning it to a variable first.
ARGV handling is a little weird too. I understand the impulse to get rid of $1, $2, $3, $*, $@, $#, etc., but it ends up just requiring different gymnastics, like writing `set -e argv[1]` instead of `shift.
Running on a POSIX system, there are decades' worth of shell snippets out there which don't work with fish, but do with sh, ksh, bash & zsh.
Fish is just gratuitously incompatible. Having fish-users on a team is a pain, because they'll write everything in fish and either not bother producing sh equivalents, or produce insufficiently-tested sh equivalents. It's just a lot of pain and bother, and what's the benefit? Zsh does everything fish does and more, so why not just use it?
Edit: I just wish that the original fish developers had chosen to implement all their cool features and be sh-compatible, or at the very least had exercised some wisdom in where they chose to break compatibility. Instead, it very much feels like a 22-year-old's project: full of ideas, some good & some bad, and needlessly without respect for the past. I've no problem with rejecting the past when the past is broken (and sh is broken in places); my problem is with the equivalent of saying, 'hey, English spelling is terrible, soh Aiv dəseidid tū dəvelup mai ohn.'
Where stuff like fish is a pain for me is with apps that for whatever reason need shell integration (virtualenv, for example). Non-POSIX shells end up being an afterthought there, so you end up with no or buggy support, and end up having to find some other custom variant (virtualfish, etc.) to get good behavior. Sticking with a more mainstream shell tends to be safer there, and zsh barely makes it over that line.
* zsh-syntax-highlighting: https://github.com/zsh-users/zsh-syntax-highlighting
* My zshrc, for what it's worth: https://github.com/burke/dotfiles/blob/master/.zshrc#L173-L1...
really, really cool
[1] https://github.com/larkery/zsh-histdb
See http://zsh.sourceforge.net/FAQ/zshfaq03.html.
This. It's an awesome shell, but I couldn't set is as a default because my already done shellscripts and aliases would stop working. And I also can't set it on server, because then a deployment tool logs in, and expects bash.
And if it isn't default, I might not bother, I'd forget to run it manually most of the time.
(The worst offender is replacing && with 'and' - why not at least enable both and preserve compatibility?)
oh-my-fish [1] plugins is a good place to see (part of) what is available
[1]: https://github.com/oh-my-fish
We are in the process of scoping a major release (fish 3.0) that can include major syntactic changes. If there's an aspect of fish you would like to see changed, now is a great time! Of course we'll read the comments here, and our issues page [1] is where discussion happens.
We're also welcoming new contributors. It's easy to get started writing completions or with the issues labelled "easy-pick". The core code base is reasonably modern C++ too.
http://github.com/fish-shell/fish-shell/issues/
I implore you to NOT use JSON or ProtocolBuffers, neither are appropriate formats for configuring my shell, or storing long sets of textual data. Protocol Buffers is hardly the kind of format I want to parse and read my history in, and JSON is a less than ideal configuration format for many reasons.
https://github.com/vstakhov/libucl UCL (Universal Configuration Language) is a much more appropriate format for configuring programs than JSON, and is has been accepted as standard for use configuring all tools included in the FreeBSD operating system.
I also suggest you consider using a different language to store shell history, since shell history and shell configuration are two very different jobs with different goals and trade offs. I personally would suggest a simple safe format like TOML https://github.com/toml-lang/toml for storing the history.
But If you do want a single format for both configuration and history, I would implore you to pick TOML not JSON or Protocol Buffers.
Protobuf (or any other binary format) has the benefit of being faster to load, but I agree - it should not be be used to store things like history. It should be easy to parse history without having to write code. And with Protobuf, you need the schema.
If a binary format is going to be used, it should be optional - or perhaps there should be tools to convert the history file to/from a plaintext format.
Also since he’s the kind of person that a HN reader will probably Ike to know more about. The original author of the aforementioned uclcmd, Allan Jude [http://twitter.com/allanjude], is the former host of the TechSNAP podcast [http://www.jupiterbroadcasting.com/show/techsnap/], current host of the BSD Now podcast [http://www.jupiterbroadcasting.com/show/bsdnow/], a current member of the FreeBSD Core team, and co-authored not one but two books on the ZFS file system FreeBSD Mastery: ZFS [https://www.amazon.com/FreeBSD-Mastery-ZFS-7/dp/0692452354/] and FreeBSD Mastery: Advanced ZFS [https://www.amazon.com/FreeBSD-Mastery-Advanced-ZFS/dp/06926...]
TOML is definitely an interesting choice if a text format is deemed necessary however. Array of tables syntax should be a fine syntax choice for storing history.
I totally drank the SQLite koolaid a long time ago.
https://stedolan.github.io/jq/manual/
http://jsonnet.org/
Both are single binaries, so easy to run them where you need it. I don't know comparable stuff for the other mentioned formats, whenever I need to deal with yaml in scripts i run
https://github.com/bronze1man/yaml2json
I would be totally fine with any format that can be converted to JSON on the fly. Of course I would love to have something like these tools more integrated within a shell, but the representing text format on the disk is not that important for me.
We're open to a lot of things (except "make it fully POSIX-compatible"). We're still trying to not massively break everything, though.
The sort of things we've discussed include:
- Not expanding `{}` so you don't need to quote it with e.g. `find -exec {}` (currently this is read as a zero-element brace expansion, i.e. it expands to no argument)
- Removing the `?` single-character glob because it's apparently entirely unused and is another special character to remember (in fact we've also talked about removing `^` as a shorthand for redirecting stderr and `%something` process expansion)
- Allowing `$(command)` command substitutions, which could be used inside quotes as well (long term, these would replace our current `(command)` style)
- Possibly removing the special handling we have for $PATH, $CDPATH and $MANPATH (these are treated by fish as lists, which is nice in some ways and causes pain in others)
For a general overview, see [the fish 3.0 milestone on github](https://github.com/fish-shell/fish-shell/milestone/18).
Thank you for leading the charge on modern command line design.
[0] https://fishshell.com/docs/current/design.html
[1] https://www.pgcli.com
[2] https://www.mycli.net
Thanks for both your work on fish and for your blog!
but similarly, fish user for the last 2+ years.
In fish Alt+Up does something similar, but repeated presses iterates over all words of all commands rather than last words of bash commands. A big improvement is you can type some chars first and then Alt+Up only gets words matching this substring — like Up but word granularity! (Closest bash key is Ctrl+Alt+I)
If you don't mind the differences, and want Alt+. muscle memory to work in fish too, do:
(plus Alt+Up doesn't work for me in linux console, Alt+. does)``` function sudo if test "$argv" = !! eval command sudo $history[1] else command sudo $argv end end ```
This works for `sudo !!`
https://github.com/srynot4sale/dotfiles/blob/master/fish/fun...
Unlike bash, fish even expands it in place, allowing you to make changes.
Only one more key press than "sudo !" :)
Maybe adopt a package manager for plugins too? ;)
With ZSH, I can run a command with a space at the start so it's excluded from history, even though its not saved to disk, the last command is still stored in memory so I can press Up to access it again.
This is handy when a mistake is made in the command means I need to run it again with some small change.
[0] https://github.com/psprint/zsh-navigation-tools
That and support for
(not having to prepend "env ") are what's stopping me from recommending fish to others.Btw: Big thank you for fish, it's awesome!
It's no dealbreaker though, I still use fish and love it :) Just a minor annoyance ;)
Other than that, my biggest pain point with fish now is that it doesn't interact well with pkg-config (issue #982) and the workarounds for that are a bit awkward. eval is scary and may require double-quoting the non-pkg-config parameters, and string splitting can wrongly split inside quoted text.
e.g. apt install foo # you need root permissions to install, won't work sudo !! # will expand to sudo apt install foo, and it'll work!
1. equivalent of `set +x` and `set +e` from bash (to echo commands and stop script execution on the first non-zero return) – https://github.com/fish-shell/fish-shell/issues/3427,
2. Associative arrays – https://github.com/fish-shell/fish-shell/issues/390
What I don't like is that after hitting Tab twice when doing path completion, the list of possibilities comes out, allowing arrow keys to be used for selection. The problem is that it requires pressing Enter to confirm the suggestion and I fear of executing the command with incomplete path prematurely (it's just one more Enter hit away).
It's a Python-based shell that attempts to be somewhat bash-compatible (for ease of use over, e.g., IPython). Instead of making a new scripting language (fish), go all in.
Pros: scripting is amazing. ( while True: ls ~ ) Cons: can be a bit slow (because Python interpreter).
[0] https://github.com/fish-shell/fish-shell/issues/438
This in turn means I’m willing to install it with no hesitation in all my local and remote logins, so I have a uniform simple setup everywhere.
Is there a way to disable this?
One issue is the behavior of globs. I often want to do "scp host:directory/* ." but you can't do that in fish, so I drop to bash. That's pretty much all I drop to bash for.
Like fish, it'll interpret an unquoted asterisk (sorry HN formatting) as the glob character. So it tries to match pathnames to `host:directory/`.
Only the default bash behavior (if "nullglob" and "failglob" aren't set) is to pass the literal glob expression if no match could be found.
So once you `mkdir host:directory; touch host:directory/file` (which you can do - this is unix, so almost all pathnames are allowed), this will be broken.
This means you _should quote the token_ in bash, which is exactly what you should do in fish.
Note: This is also why you might see code like the following in bash:
See http://mywiki.wooledge.org/BashFAQ/004 and http://mywiki.wooledge.org/glob#nullglob for more info.https://github.com/fisherman/fisherman
[0] https://github.com/junegunn/fzf
Wait... Is whitespace significant?
1. Support for last command by !!, as in `sudo !!`.
2. Ability to search history from a partial command like `git checkout`, where up arrow would step backward from the present.
I wish all my tools were as friendly as fish!
We have that feature, and it's enabled by default. Just type the partial commandline and press up-arrow. Or do you mean something slightly different?
My original reason for using fish was onboarding junior engineers. I had a pretty fancy zsh/emacs setup, and they'd ask me how to make their shell do that (reminder: on macOS you get bash3.2 by default!). So I switched to fish/spacemacs, so the answer isn't "uh sure you can rsync 50MB of accrued elisp".
Result: I have a nice zplug[0] setup now:
Still easy to reproduce. Maybe consider some of those plugins. You don't have to give up being POSIXy. Whether or not that's good or bad, I leave up to you :)(Commented out bits are things I'm playing with: mostly to improve shell startup time.)
[0]: https://github.com/zplug/zplug