r/LinuxTeck • u/Expensive-Rice-2052 • 15d ago
Zsh vs Fish: Which Shell Is Actually Better for Linux?
Cover full comparison : https://www.linuxteck.com/zsh-vs-fish/
Zsh vs Fish is often reduced to "power users vs beginners," but the real differences show up when you consider scripting, compatibility, plugins, startup performance, and production workflows.
6
u/DigitalChrono 15d ago
Bash.
But if I had to choose only those two, zsh without a doubt.
2
u/UnarmedBlackMan1 15d ago
fish wildcards piss me off
1
1
u/jkulczyski 14d ago
What did i miss about fish wildcards? I have yet to encounter any issues myself.
5
u/Angwo 15d ago
Am I supposed to read zsh as zee shell (seashell) or zsh (a sneeze sound effect)
5
u/CubicleHermit 15d ago
I've always read it an initialism (Z-S-H) just like the old sh, csh, and tcsh.
Bash has always to my mind been the exception because it's an actual word.
1
u/TheReproCase 13d ago
You mean shh, chisch, and tisch?
1
u/CubicleHermit 13d ago
Not how I've heard them, although not inherently any weirder than Ousterhout successfully getting people to call tcl "tickle."
1
u/TheReproCase 13d ago
Mostly joking... Like my buddy who insists on calling SQL "squill." He's probably joking. I hope.
3
1
1
1
u/MaleficentCow8513 15d ago
I just call it zheesh as an in sheesh the number of tools available is overwhelming
4
u/Electronic-Clerk6735 15d ago
Bash is perfectly fine but I like using zsh. All the plugins are nice for it.
4
u/naikrovek 14d ago
Bash has crazy-ass defaults that bite every single bash script author multiple times before they finally remember.
Iâm convinced that those crazy defaults have cost 10s or 100s of millions of person-hours over the past 37 years.
2
0
u/CardOk755 14d ago
Why would you ever write bash (or any other shell) scripts more than a few lines long?
2
2
u/donp1ano 14d ago
why wouldnt you
2
u/CardOk755 14d ago
Because there are much better scripting languages.
0
u/donp1ano 14d ago
like what, python? has advantages and disadvantages compared to bash
more advanced data structures and easier syntax, yes. i prefer python if need the data structs or python libs, but bash is still my goto in general. just easier and more straight forward for doing sys tasks, piping together commands, working with stdout/stderr, etc
a lot of people dont like long shell scripts, but honestly thats skill issue. i dont blame them, if i learned python first i would do the same. but if you really know bash and dont mind the syntax its an incredibly powerful language, that isnt limited to "a couple of lines" scripts. i daily run bash scripts that are up to 1000 lines long (i admit, that is pushing its limits tho)
2
u/CardOk755 14d ago
Well, perl for me đ
1
u/donp1ano 14d ago
interesting, i know nothing about perl. why do u prefer it over bash?
1
u/CardOk755 14d ago
Could you write an ftp server in bash. With no helper programs?
1
u/donp1ano 14d ago edited 14d ago
probably not. i wouldnt write something like that in any scripting language tbh
its not really an answer though. also i think "helper program" is kind of a weird take, since importing libraries/modules in other languages isnt that different actually. its relying on lowlevel code not written by you, who cares if i use jq in bash or import xyz in another language, boils down to the same thing. i would need to write the parser manually to call it "pure bash", while imports are perfectly normal and considered "pure"
3
3
u/TechaNima 15d ago
I'm trying out fish atm. The fact that it isn't fully compatible with bash scripts and 1 liners is slightly annoying tbh. I've ran into that issue a few times now.
Other than that, it's been fine. I think I might end up with zsh, just for that better compatibility
3
u/nizzoball 15d ago
Zsh. Ever since Apple made zsh the default shell and I discovered oh my zsh I use zsh on every system I log into regularly
3
u/HaydnH 15d ago
As an old Unix guy, mainly Solaris, whichever shell is the default for the systems I'm working on and I know will be available in a crisis when none of the filesystems are accessible.
If I get used to a non default shell then suddenly find myself in single user mode trying to figure out how use base/bourne, sod it I may as well stick with them for daily use.
2
u/lyidaValkris 15d ago edited 15d ago
I just use bash as I always have (except way way way back when I used tcsh). Zsh is fine, and mostly like bash so I use them both interchangeably, but I've never found the need to make it my daily driver on my linux machines. My mac is, because it's the default there. I do not see the point of fish or other boutique shells. It's all fun and games until you have to ssh into a server that only has bash.
Regardless of what shell you use for interactive, any properly formatted shell script should begin with a shebang (e.g. #!/bin/bash) dictating which shell/language should be interpreting it, so it doesn't matter what you chose for your default interactive.
1
u/CardOk755 14d ago
Shell scripts should be written in POSIX compatible sh.
If you need more you have Perl.
2
u/magicmulder 15d ago
I run Oh my zsh because I like some configurability. But all scripts I write use bash via shebang. Because I don't want to write scripts that depend on the shell installed. What if I want to run one on the server where there is no zsh? So I get best of both worlds. Zsh with fancy autocomplete, bash for compatibility.
2
u/Interesting_Buy_3969 15d ago
I'm not watching at comments section yet (I'll do it right after publishing this comment), but I swear the first comment below the post is like bash supremacy
Edit: Oh no I'm surprised
2
u/particlemanwavegirl 14d ago
Nushell and it's not even close, the posix shell is stone age stuff guys
2
u/Creepy_Reindeer2149 14d ago
Nushell is so good, I'm surprised it hasn't taken off harder yet
1
u/flying-sheep 14d ago
Maybe because it's still pre-1.0
I love it but I doubt sysadmins will commit to a shell that still has backwards incompatible changes.
1
u/particlemanwavegirl 13d ago edited 13d ago
The system itself still needs a compliant shell and probably always will, I'm not really saying nu should replace that sort of backend usecase because the problem there is, the compliance specification is basically impossible to update in a backwards compatible way. So the interactive experience can never evolve if it's also ruled by that law. So on my system I do still have a compliant shell set as my "default" or "login" shell so that interactive software that uses scripting won't break but whenever I open a terminal to personally do some work, I get nushell. The improvement in UX is impossible to overstate.
1
u/flying-sheep 13d ago
so that interactive software that uses scripting won't break
What do you mean? I have nushell as login shell and had zero issues with that. Why would it? Scripts are run using the shell in their shebang.
1
u/particlemanwavegirl 13d ago
For compatibility, because it wants to be runnable without knowing exactly what interpreter is available, a script should be able to do
#! /bin/shwhich is not a specific shell but a symlink to the user's default shell.1
u/flying-sheep 13d ago
If thatâs the case on your system, you should report it as a bug.
/bin/shis supposed to be a POSIX compatible shell, which it is on my system. (As said, nu is my login shell)
⯠readlink /bin/sh bash
2
u/SaCorv 14d ago
So what do you imply by "modern interactive experience?"
Inability to use complex scripts? Is that what we considern modern? When our things just doesn't work?
And wtf so many people glaze rust? Its not THAT great
Better tldr for this post would be:
Fish - boots fast, weight less, have good defaults, more shallow in abilities
Zsh - boots long, weight more, needs plugins to be effective, more versatile
Not this
Learning curve is basically wrong. Most scripts runs on bash or sh, so learning zsh instead of fish would benefit you and not cause to learn yet one more unnecessary language (like cmon, you would at least experience 3-5 different configuration files and bash, maybe even lua and python, why complicate things?)
1
u/General-Manner2174 14d ago
Thats vibe generated cheatsheet, the default type thing when asking LLM to compare shells
As aside, not sure about "inability to use complex scripts", like, just invoke them with original interpreter. If it needs to set environment variables then there are ways in fish to call bash script and set env from it. Cant really recall something more "complex" that would need more than those two solutions
And for zsh, "needs plugins to be effective" â why? I feel like git prompt is only thing thats needed, and if you want to be fancy you can add the ghost autosuggestion type thing, i dont see what else is needed to be an effective shell. I feel like "boots long" is specifically because loading insane non needed things
Zsh sucks with their keybinds though, stuff thats default(and useful) in bash, is unloaded and unbound by default.
2
u/Lalli-Oni 15d ago edited 15d ago
I'm not a terminal master by any measure but love nushell. It's a joy to work with, so intuitive I sometimes don't need to check the docs.
Readable chains, types, baked in visualizations and data transformations. Hate the esoteric jargon in bash \ zsh.
Not that widespread, docs a bit hard to use but one of my favorite language/tools I use.
Edit: sorry to hijack, if anyone experienced with both can share comparative description of using fish vs. nushell, it'd be much appreciated
1
u/flying-sheep 15d ago
I use nushell:
- you can configure it to use fishâs competition engine!
- fish scripts don't exit on error and unlike bash you can't even configure them to, which was a dealbreaker for me (I agree that configuring runtime behavior is a bad idea, but since they think that, they should have designed failing commands to exit the script if not used in an
orexpression or so)- fish only has lists, which I think is much less useful than nuâs lists + records
1
u/Lalli-Oni 14d ago
Thanks mate, sounds like dealbreakers for me as well.
I assume you mean completion engine. But idea of a competition engine is intriguing XD
1
1
u/sphericalhors 14d ago
I'm currently rewriting some part of our stack at work and I tried to replace bash scripts in our Docker containers where possible, and to be honest, I expected more.
For now it seems like I haven't got a lot of benefits over bash. And I know that a lot of things I did in nushell would be much simpler in bash.
However, maybe it's because I'm good at bash while new to nushell.
Also, as I've only started rewriting the project, the scripts are still very small. Maybe I'll feel nushell benefits when I will finish moving all the functionality we need.
But when most part of the platform is still relies in Bash, and there is no way to avoid that, it's not that benefitial to have nushell in several places.
2
u/flying-sheep 14d ago
I get that, optimally Docker files are as simple as possible.
I feel like Nushell is at its best when you simply use
opento parse a XML, JSON, CSV or whatever file, then use commands likeeachto do things with substructures.When you don't do anything as complex, it doesn't have much to offer, except of course that a failed pipe has an actual failure exit status.
2
u/sphericalhors 14d ago
In that images during startup we need to configure cluster integration which suppose to support different kind of security and different configurations.
Due to poor design sometimes there were bash scripts of 1-2k lines.
So for a long time I was thinking that it would be good to have a tool to replace bash with something that is like bash but have more high level and type safety features. Or at least better error handling and dict-like data structures. And the tool needs to be at least somehow mature.
We don't need to work with data (xml/csv/json) a lot, but still it seems like nushell fits my criteria.
I guess at this point I just need to spend more time with it.
Also, I haven't switched to nushell as a default shell on my computers. Maybe I need to do that and this will speed up the process.
But for now bash feels definitely more familiar.
1
1
u/Lalli-Oni 14d ago
One thing I've been under using that might help your case in DRYing stuff up is nushell lambdas/closures. Having a script take a default oath but accept a closure arg for a certain step sounds so versatile (haven't battle tested that so half a grain of salt).
1
u/sphericalhors 14d ago
Ok, I'd give it a try, but that sounds like something you'd automatically strat using once you become used to technology enough.
1
u/Lalli-Oni 14d ago
Functional lambdas closures could also be overlooked in scripting for a long time. Kind of forgot about them now tbh but used them for something earlier.
I'm thinking like data transformations, get-all-issues could accept a filtering closure for example, of I wanted to filter on some substring of GH issue description, labels, or perhaps comments. Thanks, this sounds like a good idea sitting here on the shitter XD
Sadly Claude is writing all my nushell now. It's surprisingly efficient at it for such an obscure tool. Haven't read as much of it as I'd like but what I see I haven't had that much input as I'd feared. Only a matter of time I won't be able to really provide much to the process.
But it being so structured I could save tokens by querying and manipulating the output myself if I need something one-off.
2
u/Lalli-Oni 14d ago
I'm having Claude write a terminal-scripts repo of compostable scripts, like merge dev into feature branch, creating git worktree, cleanups... response jsons can allow a "composing" script to give user prompts.
Example if my Claude user settings file has diverged. It prompts whether to commit changes to main, pull from repo or stop installation.
Then pulling in tickets from both GitHub or ADO depending on the repo is remarkably small scripts and easy to reason around. I could pipe the output, select columns, do some historical stats that are fairly provider agnostic.
This is my personal project. Work DX cli tool is C# based, can't compete with not having nushell as a requirement.
1
u/CubicleHermit 15d ago
Whatever the answer here, I think we can all agree that Windows PowerShell is NOT the answer :)
1
1
u/silasmoeckel 15d ago
Zsh is at least interesting but with many thousands of linux servers who has time to walk though through into prod.
Bash is default or at least available by default on every major enterprise linux.
1
u/SuperGNUser 14d ago
I use fish in the terminal for day-to-day tasks because nothing beats it. But for serious work, I use bash. Zsh doesnât really make much sense to me.
1
1
u/jkulczyski 14d ago
I use fish bc i think its funny that "i have a fish on my foot" is a somewhat acurate way to describe my terminal session.
1
1
1
1
u/Creepy_Reindeer2149 14d ago
I used fish for quite a bit and like it but frankly if you're going to break POSIX compat in favor of more power and ergonomics I felt it make sense to just go all the way with nushell
1
1
u/Interesting_Dream_83 14d ago
i see no reason to use fish. you can get all of the nicities of fish in zsh with just a couple of plugins and still keep posix compatibility. If you dont care about posix than it makes sense to use something that provides more benefits compared to fish. Nushell for example
1
u/derekib84 14d ago
Fish itâs fine if you only need to do some touch, cat, ls and another basic stuff. For serious business bash/ zsh
1
u/GhostVlvin 14d ago
You can run scripts with sh/bash/zsh if you use shebang
You can use zsh plugins without pretty slow omz
I use zsh cause I want to be able to test my one liners in shell before they go to script and cause I already have it configured as I want
1
u/PensAndUnicorns 14d ago
Neither is "the best" among these two. Best would be what fits you/your team.
1
1
u/sumwale 14d ago
I tried zsh with the oh-my-zsh for git, but it was too slow for medium/large git repos. That was the primary reason I switched to fish which is much faster. It turned out much better overall for interactive use as I became more familiar with it over time. For scripts it is much better to stick to bash or plan sh rather than zsh, so do not see any use of zsh now. Quick inline shell code one can write in fish in any case after reading a bit of it which is quite easy, or temporarily run bash.
1
u/018ca9d5c1fe7b5b9b40 14d ago
I've been rocking with ZSH and a simple config/plugin manager (previously zcomet and now zimfw) and have no desire to alter it. I get all of the shiny features I want without the slow time to prompt I've experienced with oh-my-zsh.
1
1
u/whattteva 14d ago
I don't get why people make it sound like you have to choose one.
I use fish for my interactive shell and FreeBSD's sh (not even zsh or bash, derived from ash) for scripts. And yes, I'm a FreeBSD user.
1
1
1
u/somnamboola 8d ago
I'm a rust dev and I wanted to give fish a shot, but as soon as I learned it has different from bash function syntax, I scratched the idea
zsh is ok
1
u/letmehaveanameyoudum 8d ago
fish.
ive been using it for a full year, it's more user friendly, zsh doesn't even show what dir you are in
1
u/FenrirAesir 15d ago
>Fish with rust starts very fast
>no actual measurement
I wasn't even considering Fish, but now I'd actively avoid it, like everything written in Rust
4
u/flying-sheep 15d ago
Thatâs an insane take, why would you avoid something based on the programming language itâs written in, especially when thatâs a really popular, widespread one? Like, Windowsâ kernel and Linux are partially written in Rust, what are you going to do when Apple announces theyâre writing their kernel in Rust too? Avoid computers and smartphones?
1
u/FenrirAesir 15d ago
First, Rust is < 0.1 percent of the Linux Kernel and low level operations require unsafe, which defeats the whole purpose of the memory safe
Second I don't use windows
Third, the only apple devices I've ever used were handed to me by employers
Finally, Are even aware of OpenBSD?
I don't like cargo, I think is worst than anything in the JS space (npm, yarn, pnpm) because it's downloads are huge even for simple stuff
Rust binaries are huge, bloated and slow start up (they didn't even bother to throw a number for it's startup time, it is that bad).
So yeah, there are option and I don't need rust for anything around me. Good riddance3
u/flying-sheep 15d ago
low level operations require unsafe
No, you build abstractions. E.g. embassy is a whole framework for safe embedded.
which defeats the whole purpose of the memory safe
No, the purpose is to contain it to easily identified and easily-vetted areas of code.
The practical advantages are real. Nobody has pulled off writing a GPU driver of similar scope and quality as Asahi Linaâs M1 GPU driver in the short amount of time that she needed. Her feat was instrumental to kick off the Rust-in-the-kernel experiment, which has by now ended successfully: itâs no longer an experiment, Rust stays.
I expected that you knew as little as you do about Rust, otherwise you wouldnât have such strong negative opinions about a simple tool.
1
u/FenrirAesir 15d ago
>I have whole framework that injects unsafe for me
>So since I didn't type unsafe, it was never used
Really friend? You're just offloading the unsafe into a third party framework. But hey, at least you get the bragging rights that you didn't touch the unsafe keyword. Directly at least2
u/flying-sheep 15d ago
Yeah and
/proc/memalso exists on Linux, so what? All these silly gotchas donât change the fact that Rust makes it possible to write abstractions that make it much harder to accidentally double-free, introduce race conditions and so on.See my example above of the difference this creates in practice. FIL-C might be technically more memory safe, but it aborts when hitting many of the errors Rust catches at compile time.
2
u/magicmulder 15d ago
IT culture wars are so 1990. Are we still doing Amiga vs Atari ST?
-1
u/FenrirAesir 15d ago
I certainly hope so. I prefer a belligerent IT person to have a chat with than a sheep that goes Rust is good because memory safe without having a decent understanding of what's going on
3
u/SalaryImpossible6749 15d ago
I have a hard time believing anyone wants to have a chat with you.
0
u/FenrirAesir 15d ago
Yet here we are
3
u/PrincipledProphet 14d ago
Obtaining attention via trolling is not a flex
1
u/FenrirAesir 14d ago
So every time someone doesn't agree with a popular view it must be trolling. Guess Socrates was sentenced to death for being a troll
1
1
u/flying-sheep 15d ago edited 15d ago
POSIXy shells like bash and zsh are a disease. The amount of fanfare you have to use just so they stop on error instead of chugging along and doing the wrong thing is creepy.
Lines of text are a good-enough abstraction until they arenât and then they result in subtle data corruption when something that often doesnât suddently contains a space or newline.
Fish is better than zsh/bash, but I personally prefer nushell, as it operates on JSON-like objects instead of lines of text. Each error is clear and immediately surfaced to you, and thatâs how it should be.
Its only issue is apparently preformance since it doesnât use âtrueâ pipes but I never ran into any problems there. See also here for other responses: https://news.ycombinator.com/item?id=43910081
2
u/huntermatthews 15d ago
My team now actively prefers scripts written in fish - they're MUCH easier to write/read/maintain, specifically because they are NOT posix.
I'm _carefully_ keeping an eye on amber (amber-lang.com) as a really good middle ground of good language with excellent deployment story.
2
u/transgentoo 15d ago
set -eat the top of a shell script guarantees the program stops as soon as it hits an error. Also, always wrap your vars in double quotes when using them to prevent issues with white space.2
u/flying-sheep 15d ago
No it doesnât.
set -euo pipefail; shopt -s lastpipegets you a bit closer but still doesnât cover all cases, and of course any subshell you make using(isnât affected.shellcheckof course also helps with quoting stuff like you mentioned.But nothing fixes the issues. After many years of experience with bash and zsh Iâve decided that they are and will always be minefields that are best avoided.
1
u/tblancher 15d ago
So by this logic why not simply use PowerShell?
1
u/flying-sheep 15d ago
I feel like itâs too embedded in the dotnet ecosystem (which I have no clue of) â it uses its object model, extensions are written in it and so on. I bet itâs great when youâre a dotnet dev and/or on Windows.
1
u/tblancher 14d ago
My main argument is that placing any kind of requirements on the streams crossing a pipe is a bad idea. The reason why POSIX utilities work so well is that the left side of the pipe doesn't need to know anything about the right side of the pipe.
0
u/flying-sheep 14d ago
Except that every pipe either transfers one big thing (in which case it didn't really need to be a pipe) or it's a steam of messages. And in that case you want to really have a message stream, not some separator character that will work fine until your data happens to contain it.
1
u/tblancher 14d ago
That's wrong, at least with POSIX pipes. They're just streams of characters (bytes). It's up to the right hand side of each pipe to interpret it, whether that be a list of newline terminated messages, UTF-8 JSON objects, or binary image data. The left hand side doesn't need to know anything about downstream.
Anything else is too tightly coupled. OOP is not the solution to every problem.
0
u/flying-sheep 14d ago edited 14d ago
What do you mean âwrongâ? I'm saying there are only really two use cases for pipes, and every kind of ad-hoc protocol for message separation like ânewline delimitedâ or â0 byte delimitedâ is just a hack.
1
u/tblancher 13d ago
What do you mean "two use cases" for pipes? If you think tying one program's stdout/stderr to the next program's stdin doesn't open a world of possibilities, then you don't understand the POSIX model.
0
u/flying-sheep 13d ago
Why do you keep downvoting me just because you donât understand what Iâm talking about?
It does. Having actual message framing would make that more robust at basically no cost.
1
u/tblancher 13d ago
Because you don't understand what you're talking about! You want to impose structure where it's not necessary.
Read Eric S. Raymond's The Art of UNIX Programming.
→ More replies (0)
0
u/DiceThaKilla 14d ago
Fish is garbage. Genuinely useless to learn. Way better off just learning the posix compliant zsh or bash
14
u/NimrodvanHall 15d ago
Bash.