My ls usage went down 100% after I switched to fish shell. The built in Alt + l command lists the directory contents. Very helpful! And also results in a cleaner shell history.
One pet peeve of mine is "human readable dates", especially for a directory listing. If I'm scanning for something I copied into a folder yesterday amongst other things, I don't want everything to show "1 day ago" if I'm looking for something I did around 11am. I want the dates and times. That goes for forums like HN. Show me the date/time and also "7 hours ago" or whatever if you have to.
I've never understood taking that information away. I wonder if it's a consequence of infinite scroll or something.
I agree. GitHub does this too on commits. "foo.cpp modified last year." It makes no sense, at least without the ability to view additional datetime information.
You can hover over the date for an exact timestamp. Maybe someone can write a userscript to replace the relative dates to exact ones.
the point is that you should not need to hover over the dates to get the exact ones.
it hinders fast viewing of the data, when it is more than a small amount.
Depends on the application and your personal preference. It's way "faster" for me to see a HN comment was posted "1 hour ago" than it is for me to see the absolute time string and do the math myself. Further, I don't care about the exact time a HN comment was made. I care about roughly how long ago it was posted so I know if the conversation is still going.
But if exact dates/time is shown you have the possibility to mentally subtract one hour from what the time is, and look for that.
With 1 hour/week/month/year you cannot go the other way, it is too vague.
But web pages and apps should provide a quick and easy way of changing between the too formats.
the point is that you should not need to hover over the dates to get the exact ones.
For you. For some, you should not need to hover over exact dates to get humanized relative deltas.
Yeah this makes it better, but I've found some sites that don't do that, blogs and news articles where it's impossible to find the date of published... Is it a SEO trick to make your content always relevant?
Well it will definitely help with caching. You only need to update the article every year or so.
That's still more than just using an exact date that never needs to be updated. Also that seems like something you would do client side anyway. ie. you send a timestamp that never changes and then have the client convert it to "X years/days ago."
This bookmarklet (I prefer to do it on purpose, not by default) would do this on a GitHub page. It is easy to convert it to a userscript.
javascript:(function () { document.querySelectorAll("relative-time").forEach(function (el) { var p = el.parentNode; var t = el.title; var s = document.createElement("span"); s.innerHTML = t; p.removeChild(el); p.appendChild(s); }); })();
Shorter version
javascript:(()=> {document.querySelectorAll("relative-time").forEach((el)=> el.format="datetime")})()
based on docs at https://github.com/github/relative-time-element
you can also do other formats like
document.querySelectorAll("relative-time").forEach((el)=> {el.format= "datetime"; el.year ="numeric"; el.weekday=undefined;})
shortened version still using <span>, as that has better line wrapping:
document.querySelectorAll("relative-time").forEach((el)=>el.replaceWith(document.createElement("span").innerHTML = el.title))
Can’t hover on mobile
You can hover with a pen like the Galaxy S Ultra has. But it doesn't work.
Huh, I never noticed that. There is a lot of sublety in HN's minimal formatting.
Particularly when many systems I've seen group the past three years into last year.
It feels like the categories are:
"Today, Yesterday, This Week, This Month, Last Year, Big Bang"
Gitlab considers everything older than 0.49 years to be "a year ago". Since it's July, that means commits from January 2024 are "a year ago" now!
So annoying, I wrote this extension some time ago to get rid of relative dates in github
https://addons.mozilla.org/en-US/firefox/addon/yyyy-mm-dd-gi...
Yes. If we are in the middle of the current year, modified last year could mean anything from half a year ago to one and a half years ago.
Often I want to see exact what time I made a commit to correlate it with some error code and it’s only giving it by day. Such a bummern
This is a setting, you can change it to any other date format you want.
Yep, `--time-style`.
Yeah that is such an amazing anti-feature. And how do you deal with changes? Like, when does 1 day ago become 2 days ago? According to google it becomes two days ago after 48 hours. That means if you look at your phone after 47 hours it will say 1 day ago and you'll be tricked into it happening yesterday. Human readable my ass.
Or, you know the specific day because it was the day after your friends birthday or whatever. And you try to find a specific item, but you have to sift through an entire months of shit because all the information you get is "three months ago".
The intent make sense (humans are better at durations than with absolute timestamps), but the lack of granularity is ridiculous. It should be "1d 20h ago" or based on the dates in question maybe more or less granual. (It's a hard UX problem, but that just means that the program ought to know what the user wants. What's important to them. Are the searching for something? What patterns to highlight? Ie. if there's a directory with a 1000 files but only 2 old ones maybe put some emphasis on them, etc.)
You can hover over the time on HN and get a timestamp.
Not if you are on a phone or similar device, which lots of people are. Important info like that should never be only accessible by hovering a mouse pointer that may or may not exist.
I wonder if sites could use the HTML <time> tag for this. They could choose the human readable format but still give us the time so that it could be replaced or overlayed with some extension.
I always try to use it when writing HTML.
(https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ti...)
One thing I really like about all of the ago formats:
- What it says: 1 year ago
- What it is: 1 year and 10 months ago
Yes, I hate that approach too. I think it started with either Web 2.0 startups (I was working with one at the time, that implemented that in their product), or with Google and suchlike companies around that time, in their general web apps or social media web apps.
I agree, they should provide the detailed time, then provide the days ago thing too, if they want to.
There is also 'lsd' but I still prefer eza.
For everyone interested there is a lot of modern command line tools I nowadays prefer over the old stuff:
bat - cat with highlight
difftastic - better diff
gdu - ncdu for ssds (disk space analyser)
zoxide - modern cd
fd - find alternative
rg - ripgrep (grep)
fzf - fuzzy finder
jless - json viewer with mouse folding
dra - download and install release assets
lazygit - git TUI
lazydocker - docker TUI
yazi - file manager with image preview
zellij - better tmux / screen
starship - cross shell prompt config
Have fun4 additional tools I use regularly:
- task, a Makefile alternative
- hyperfine, a benchmark tool
- vegeta, a load testing tool
- sd, a better, more intuitive sed
There’s also the JSON trinity:
- jq, the well know JSON processor
- jc, convert the output of many CLI tools to JSON
- gron, make JSON greppable
Task is _amazing_
I tried magefiles[0] for a while, but Task just works so much better and isn't Go-specific as heavily.
Justfile is my favorite. Anything that requires complexity I just use Zig build. I hate make with a passion. I could see why people stick with it after learning it for decades, but for the rest of us it is a nightmare.
I looked, just now, at all the Make alternatives mentioned: Task, Mage and Just.
Those first two are nowhere near as easy to read as Makefiles. The last one, Just, looks good, though.
At least Cmake files are easy to read, but many of these alternatives are just poor UI, compared to Makefiles. I mean, using YAML of all things and thinking it's some sort of improvement over Make syntax?
1. Mage is just insane. In what world is this:
func Build() error {
if err := sh.Run("go", "mod", "download"); err != nil {
return err
}
return sh.Run("go", "install", "./...")
}
More readable than this: build:
go mod download
go install ./...
2. Task - not just significant whitespace, but significant whitespace everywhere, due to a poor format (YAML). Look at the example given: version: '3'
tasks:
build:
deps: [assets]
cmds:
- go build -v -i main.go
assets:
cmds:
- esbuild --bundle --minify css/index.css > public/bundle.css
Compare with Makefile that does exactly the same thing: build: assets
go build -v -i main.go
assets:
esbuild --bundle --minify css/index.css > public/bundle.css
These alternatives to "Make an easier Make" appear to not know about Make in the first place.due to a poor format (YAML).
That's just your opinion. I'll take YAML whitespaces over Makefile whitespaces any day.
Compare with Makefile that does exactly the same thing
Good example in favor of Task, I prefer the explicitness :) Especially when the file starts to get big. You forgot the .PHONY by the way, I hope for you there's no build/ or assets/ folder where your Makefile is.
For a more useful comparison, with actual source dependencies and build target:
Makefile:
GO_FILES = $(shell find . -type f -name '*.go')
./myapp: $(GO_FILES)
go build -trimpath -o $@
.PHONY: build
build: ./myapp
Taskfile: tasks:
build:
cmds:
- go build -trimpath -o ./myapp
sources:
- '**/*.go'
generates:
- ./myapp
Makefiles are incredibly terse, but that's not an advantage. I read my code more than I write it, so I favor explicitness .For a more useful comparison, with actual source dependencies and build target:
Makefile:
GO_FILES = $(shell find . -type f -name '*.go')
./myapp: $(GO_FILES)
go build -trimpath -o $@
.PHONY: build
build: ./myapp
Taskfile:
tasks:
build:
cmds:
- go build -trimpath -o ./myapp
sources:
- '\*/*.go'
generates:
- ./myapp
Even in this example, what is PHONY needed for? GO_FILES = $(shell find . -type f -name '*.go')
./myapp: $(GO_FILES)
go build -trimpath -o $@
Honestly, it's still simpler to read.Makefiles are incredibly terse, but that's not an advantage.
Brevity is not why I prefer Makefile syntax over YAML, readability is. The minute you start trying to do anything large in a YAML definition you're going to need special editor help to keep track of indentation, and even with that, a large tree is still going to be lost off-screen because the context of any node in the tree depends on seeing the lines immediately above.
With Makefiles, any node in the tree has immediate context on the same line (the dependencies) which makes it very readable to me. I really prefer:
target: dep1 dep2 dep3 dep4
compared to: tasks:
dep3:
cmds:
- ...
sources:
- ...
generates:
- ...
dep2:
cmds:
- ...
sources:
- ...
generates:
- ...
dep1:
cmds:
- ...
sources:
- ...
generates:
- ...
target:
cmds:
- ...
sources:
- ...
generates:
- ...
One day I decided to design a Makefile alternative, but I wanted to use YAML to benefit from the standard syntax and JSON schemas. I quickly realized I was just reimplementing Taskfile with different key names.
I love Task because it completely fits my mental model, I can use all the Makefile features I like without relying on arcane syntax.
Cool. Some new ones there. I usually use a script with dra to download my release assets to `$HOME/bin`
I also use `oha` (Load Testing), `btop` (better top), `rmlint` (find duplicates) and `cheat` (similar to tldr - short manpages).
There is a blog post / video that shows how to integrate fzf with git, bat etc... it's one of the best videos I've ever seen on terminal productivity:
https://www.youtube.com/watch?v=mmqDYw9C30I
This guy is bonkers - take a look at his other videos, too
hyperfine is absolutely brilliant. My go-to replacement for time.
Those are all very nice! I've come to be a huge fan of just as a Makefile replacement for the common case where I'm not actually computing vast build dependencies.
I didn't find zellij to be better than screen. The tabs/screens are not numbered correctly so switching directly to them requires manually counting. A non-starter for me.
If you don't like the default tab bar, you can use the zjstatus plugin (https://github.com/dj95/zjstatus) to replace it with a customizable one that can show the tab index.
From memory the index is different to the position, so if you rearrange our delete tabs the numbers become meaningless. I submitted a PR but the developers wanted it to be a separate plugin for just this. I decided it wasn't for me.
This link also has a large list of additional tools I hadn't heard of but look interesting.
this one is maintained
I use du-dust over gdu, but otherwise my list is almost identical to yours.
Thanks. I will definitely try that out.
Gotta love Rust (in which most if not all of these tools are written).
As someone who defaults to lsd, is there any reason why you prefer eza to it?
Great list! I would also add:
viddy, a replacement for watch that includes history
I have a problem with all terminal tools that insist on using colors to distinguish between various file types or attributes etc ('ls' is often set up like that too for distros, but I simply delete the config which sets that, the default doesn't). I use a terminal background which is easy on my eyes, and those color schemes always include colors which clash with the background or makes them hard to see in other ways. In short - I don't want colors in my 'ls' or 'ls' equivalent output. I'm fine with what ls with '-AFC' gives me.
If tooling would simply use the Base16 Framework[0] instead of arbitrary colors from “256 color” or “RGB” color modes, this would be much less of a problem: the output would always be displayed with (presumably) readable colors defined by your terminal.
As a CLI tool author, I don't understand how I can use base16 to "theme" my tool's output. Can you point to some resources?
I'm not sure if eddyg had a different idea, but I think the following sums it up:
- base16 is a specification of how different UI elements map to colors [1], and also some tooling, configuration files, etc. to automate setting this up for many different applications.
- For a user to be able to use base16 with a tool, either:
- Allow the user to set their preferred colors for UI elements at a semantic level, preferrably in a config file, and even more preferrably in a separate file that can be included into the main config file so that it's easier to automate (i.e. I have a separate `colors.sh` that is loaded in my `.zshrc`).
- Let the user set their shell colors however they want (presumably using [2]), and use the ANSI shell colors (and a few more) according to the base16 style guide [1]. Some translation between shell colors and base16 colors will be necessary, e.g. base16 says that a language keyword should use the color base0E, which in [2] corresponds to ANSI shell color 13.
My impression is that the base16 specification is not sufficiently general for most tools to implement it in a totally unbambiguous way, but if users can set their own colorschemes with a config file, it's not hard for a user to come up with a base16-approximating colorscheme template file, from which other users can generate a config file that sets a specific base16 colorscheme.[1]: https://github.com/chriskempson/base16/blob/main/styling.md [2]: https://github.com/chriskempson/base16-shell
It’s the first 16 colors of the 256 set. Most current graphical terminals support the latter, but they only expose the first 16 in their configuration. So using them makes your software completely customizable. I believe the tty console only use the first 8.
I'm not sure that I fully understood the theming aspect but one point I think is that the standard 8/8 ANSI colors are presumably picked to be readable by the terminal theme itself, independent from your application.
So if you just use those in your application you don't know the actual colors that the user will see on their screen but you know that they will be something readable.
the output would always be displayed with (presumably) readable colors
There are several obstacles that make this not the case in practice, unfortunately. Black on white and white on black (whatever hex colors those actually are) will look fine. But different applications will use the accent colors differently. For example, some might use black text on a colored background, and others may use colored text on a black background. Some tools even use “bright” colored text on a different colored background. This is masked in most cases by iTerm2’s “Minimum contrast” setting, but when I tried to design a color palette with good contrast with that setting off, I found it to be very difficult.
Solarized is easy on the eyes and the colours are chosen for readability.
https://ethanschoonover.com/solarized/
The list on the site lacks some entries. Konsole has it built in and i bet Gnome Terminal too.
Pet peeve, Solarized makes no sense as a terminal color scheme, because it maps brgreen, brblue, bryellow, and brcyan to barely-distinguishable shades of gray. It just doesn't have enough colors in its palette to cover the range of colors that the authors of CLI tools expect your terminal to be able to display.
Also, Solarized's whole trick is that its colors are perceptually uniform in terms of lightness, and I think the results speak for themselves why we don't do this in practice. If you want a yellow that actually looks yellow and not a shade of puke brown, it needs to be brighter than the other colors (especially red, which needs to be darker than the other colors if you don't want it to look pink).
I’ve used solarised-light in my terminal for a few years. I really enjoy the colours, but you’re absolutely right, it is not actually terminal friendly. Many programs just write invisible text.
It also makes the baffling decision to make "bright black" darker than "black." Pretty much every other terminal colorscheme renders brightblack as a dark gray.
It's fine as an editor colorscheme, but nearly unusable as a terminal scheme.
It's not easy on my eyes. It looks washed out with too low contrast.
I'm totally the other way around, I rely on colorized output heavily.
But! There's supposed to be a solution to this, set $NO_COLOR to some value. https://no-color.org
Totally reasonable to file a bug report against tools which don't check and respect that env variable.
30-odd years of using ls and this comment is finally the catalyst for me to start using -A instead of -a. Thank you!
--color=never
You can use vivid [1], choose a proper theme that works for your terminal background and load the generated LS_COLORS variable into your shell.
I work on VS Code. We have a feature for this exact problem that enforces a minimum contrast ratio of 4.5:1 via shifting the luminance of the foreground text by default https://code.visualstudio.com/docs/terminal/appearance#_mini... . This feature's in xterm.js so any terminal based on xterm.js can leverage this.
We actually got a bit of push back when this was released but I haven't heard anything for quite a while now that some time has passed and we have a FAQ for colors not being "correct".
Who uses ls anyway? I tab-complete until it lists the files I need.
Just kidding. But on a more serious note, why does he claim ls is not maintained anymore?
I think they are not referring to ls, but to exa [0], which is not maintained anymore.
No, they definitely mean "ls":
By deliberately making some decisions differently, eza attempts to be a more featureful, more user-friendly version of ls.
Yes, it is marketed as a better “ls”. I was commenting regarding “maintained” in:
A modern, maintained replacement for ls.
“Maintained” is referring to exa I think.
Yes, exactly this. The original `exa`'s description is
exa is a modern replacement for `ls`
and it seems `eza` very recently changed the README to match that, given the confusion.
At the time, emphasizing it was actively maintained (in comparison to `exa`) made sense, but by now, `eza` has about 5x more daily downloads than `exa`:
Right; since the sentence mentions ls, of course, it must be referring to something other than ls.
Like when your wife finds a sexier, more romantic replacement for you, of course she's not comparing anyone to you. (Nobody is sexier or more romantic than you.) She means sexier and more romantic replacement compared to the previous lover she's just broken up with.
We do not
A modern, maintained replacement for ls.
The tag line certainly reads that way
(first line in the readme)
For some reason it became the norm to think that if some piece of software isn't updated regularly that it's inherently out of date.
For statically built executables, this might just be true.
Since when you give up shared libraries, you give up on security upgrades without needing to rebuild the world.
Or dynamically-linked binaries that are distributed via containers.
Because he's deliberately confusing "maintained" with "actively developed" in order to insinuate that the existing tools is unmaintained.
The "maintained" refers to `exa`, which is also written in Rust.
Rust binaries are static, which means they need to be rebuilt when security fixes are published on one of their dependencies.
Without active development to at least update, the static binary becomes a liability.
On another note, the developers on exa did explicitly say the project was unmaintained:
https://github.com/ogham/exa/commit/fb05c421ae98e076989eb6e8...
Of course `ls` is maintained, as a part of your shell or of coreutils.
But `eza` is a variation of `exa`, and the latter is no longer maintained, AFAICT.
Professional Linux masters just use the `echo *` shell built-in
Typing eza is a pretty horrible three character combination on a qwerty keyboard. One advantage of ls is it’s a lightning fast set of key strokes. I guess you can alias, but that’s kind of weird (compatibility, etc).
I’ve had eza (and formally exa) aliased as ls, ll and lll since around 2015 and never hit a compatibility issue.
I also have sl installed to encourage accuracy when running it…
What is 'sl' ?
Steam Locomotive, an annoying little ASCII art film to punish you for typos. Funny exactly once.
You can alias it to whatever you want though.
You can, but that's a pain to set up and maintain everywhere. I avoid using aliases for that reason, it just makes me annoyed when I ssh into a machine and it's not there.
I'm not sure the meaning behind the name, but maybe they should have picked `eya` instead, that's nice and satisfying rather than the double pinky move :D
`command -v eza >/dev/null && alias ls="eza"`
This is where an azerty keyboard shines.
this was my first reaction too
I was a former exa user, and the z is next to x on my keyboard, wasn't a huge hassle for me
Can you elaborate on why aliasing is kind of weird?
As a Dvorak user, ‘eza’ seems like an improvement! (‘ls’ on a Dvorak layout is ‘p-’ on QWERTY; both keys on the right little finger.)
GNU ls is maintained. I see commits affecting the ls.c file from 2024-06-24 and 2024-06-27; less than a month ago.
The GNU Coreutils mailing list is fairly busy also.
This project seems to be using the word maintained for the meaning of actively developed.
No the maintained here means it is a maintained (replacment) with reference that it is a fork of exa which was a ls replacment that is not maintained anymore. It does not say that ls is not maintained.
Look at the title above. It only says Eza and ls. It says eza is maintained, which tells me the other,ls, is not maintained.
Doesn’t mention exa.
Yes it’s missing nuance if you don’t click through, but that’s a complete statement, and I wouldn’t expect people to click through to get more context
Side note: the English language is a dumpster fire, and it’s easy for these issues to happen.
I strongly suspect the title could be translated into numerous languages verbatim, without losing the unintended interpretation. It is so for a few languages I know.
You can try it with translation tools.
The problem is semantic: in any language whatsoever (I suspect) if we express the idea that X is a replacement for Y, and in the same sentence mention some attributes of X, it means that those attributes are relevant to qualifying X as a replacement, which implies that those attributes are lacking or inadequately present in Y.
Without heaps of prior context, it is an impossible interpretation that the X attributes are not actually lacking in Y, but in a previously attempted replacement Z.
Absolutely nothing in the confusion here is specific to English.
I don't know why you would try to take this opportunity to criticize English when this misunderstanding could be present in literally every other language.
Because there is nothing whatsoever here that is a case of linguistic confusion or vagueness -- it is a conceptual issue of comparing two items, applying an adjective to one, and leaving the reader to wonder what that implies about the other item.
And no, English is not a "dumpster fire". Every language has its pros and cons. But there is no language on Earth that is a "dumpster fire". There is absolutely nothing productive or good that can come out of blanket, utterly unfounded statements like that.
Don’t comment based on just the title, please.
I clicked through the title, but mostly looked at code and example invocations and output.
Yes title is not clear so parent was just clarifying.
I agree with you that their usage of language is ambiguous and should be clear. I was just explaining the situation not defending the description.
It's saying "modern, maintained", implying that ls is either not maintained (wrong), or ls is not modern (can be argued to be true). Only one of those two properties need to hold for the entire label to fit.
This is referencing 'exa', of which eza is a fork. Exa was unmaintained for about a year before it was marked officially deprecated by the only person with write permissions on the repository.
It has definitely been long enough now since the forking, where not everyone is aware of exa, and this language/intent is now far less clear. I see you are not the only one to comment on this, so I think it's time to update the phrasing.
I'm under the impression that ls doesn't do very much. I'd expect it to be a small wrapper around libc.
This is thousands of lines of rust with emphasis on community building and ongoing development.
There seems to be a disconnect between engineering effort and product here which doesn't totally make sense to me. I think I'll stay with ls.
Challenge: which of the letters a to z and A to Z are NOT switches that modify the behavior of ls?
I would guess that ls has at least 50 different behaviors based on the switches.
which of the letters a to z and A to Z are NOT switches that modify the behavior of ls?
For GNU ls: e/E, j/J, V, K, M, O, P, W, y/Y and z are not used
It uses all the other upper and lower case letters, along with digit 1 and has a hand full of long options without a corresponding short one.
Edit: I double-checked the man page, I'm surprised how many are unused, I would have guessed that it uses all of them by now.
For GNU ls: e/E, j/J, V, K, M, O, P, W, y/Y and z are not used
Challenge accepted!
emphasis on community building
Probably the first time ever I hear about a community built on a freaking directory listing tool.
Definitely the first time I've heard ambition, features & especially community used as a slight.
Generally I think of most engineers I know in person as people receptive to improvements & gains. Yes they looks at costs/tradeoffs. But there feels like some strong rejectionistic / contrarianism / negativity that I wasn't expecting, that seems bizarre & antisocial to me, especially here as the top post.
ls is the archetypical example of unix gone wrong, and I think this was already widely discussed (and joked) about in early 90s (iirc unix haters had something about that). It should be just simple wrapper for readdir, but it grew into sprawling mess when it learned to stat the files too, which snowballed ls to have gazillion ways to handle all sorts of metadata
eza's scope is much larger than ls's, and has tons of additional features.
And IMO, that's sensible: ls is primarily an interactive tool (basically all uses of it in shell scripts are wrong), so adding more features that help users to better/more easily make sense of their directory listings is a net benefit, even if it makes the tool somewhat slower.
Folder icons in the terminal may sound silly, but eza uses them to indicate empty folders, among others. Colour-coded file age/size columns make parsing a directory list faster. Git columns saved my many trips through gitignore / git status. And so on.
And even through not particularly fast fuse-over-network connections it's still faster than I can type, which is more than good enough for an interactive CLI tool.
What's the point, though?
You still have to rely on POSIX and / or GNU tools in most scenarios, and if already knowing / using those, then why bother to switch to anything else?
The only time you have to care about GNU tools vs your own preference of tool is when writing scripts to run on computers running some Linux distributions, and per [1] you shouldn’t be using ls for that.
Yes but if you work professionally as a software engineer, chances are that you don't only use your PC. Being that a server that you connect remotely to develop on, or a production system where you connect to investigate a bug, or the PC of a coworker you are helping, or getting inside a container, etc.
Getting to know and use a standard setup makes you efficient in that situations, that is also the reason why I learned to use vim (since vim or at least vi you can take for granted there is on every system).
The only concession that I make is the shell, since zsh is much more convenient to use than bash, even if every time I use a system with bash I of course write some code that works in zsh and have to remember that in bash you can't do it. That is annoying, but to me it's worth it to use a better shell, not worth probably for an `ls` clone.
I just type `ls, which uses eza when I’m on my own device and ls when I’m on an SSH server. What’s the problem with that?
My setup does not deviate from that. As the sibling comment points out, `ls` responds everywhere (even powershell on Windows), it's just nicer on my local machine.
Coworker machines are whole different issue though - most of them have American keyboards (I do not), most of them do not use editors with vim bindings etc.
Use cases are different. I bet I'm not the only one who runs ls manually on my command line a LOT more than I ever use it in scripts.
I don't know how common my situation is, but I don't have any of those constraints. I have eza aliased to ls both on my daily driver and all of my work servers and it hasn't caused me a single problem.
What’s with all these new versions of GNU utilities being built with the MIT license? Seems like there are a lot of them.
The GNU project didn't invent ls. The GNU coreutils (including ls) were originally new versions of either proprietary (AT&T) or BSD licensed utilities.
Related: https://github.com/uutils/coreutils "Cross-platform Rust rewrite of the GNU coreutils"
Rust users tend to permissively-license their code in general. I don't know if there are easily available statistics but almost everything on the Rust package repository (crates.io) is MIT or Apache-2.0; certainly the most popular libraries are.
IMO the killer feature of eza/exa is not the pretty colors but the git integration - being able to see the git status of individual files in a listing (ignored, modified, etc) is pretty handy.
Totally —- any idea why eza claims exa doesn’t support it? I know that’s wrong.
I don't know, I do recall exa was a little finicky about linking with libgit2 - maybe some distros didn't come with it linked by default.
Ah, good point.
I find it strange that the README does not mention at that `eza` is a fork of `exa`.
contributions welcome
Crediting people becomes awkward when it's done by outsiders though.
eza features not in exa (non-exhaustive):
It at least mentions it's existence (though no link or context)
Seems quite similar to https://github.com/lsd-rs/lsd . How do they compare?
I know though lsd has one annoying bug when using it for grepping: https://github.com/lsd-rs/lsd/issues/1052
Well, eza certainly seems faster on my micro-benchmark as well, though in general I never have any performance issues with these tools. Btw, ls beats them both easily (in my single-directory test).
So features would be my main criteria, I guess. At least eza doesn't have that annoying bug I linked :).
Short comparison: - Eza doesn't have the lsd's piping bug - Eza has more different output from ls than I would like (by default) - Both have git support - Eza --hyperlink doesn't have "auto" mode so if I alias ls to it, ls | sed hacks will likely behave unexpectedly if I enable it: https://github.com/eza-community/eza/issues/703 and this also seems like an instance of it: https://github.com/eza-community/eza/issues/693 - Eza is slower to write than lsd :) - Eza has more options to change its behaviour than lsd
Overall I think the hyperlink issue is more severe than lsd's piping one, so I think I'll just keep using lsd for the time being.
I've used both, but settled on using `lsd`. While eza has slightly better performance, that difference doesn't usually matter for a `ls` alternative (unless you operate on very large directories) and `lsd` is nicer and feature rich.
ls -lrt
eza -lrt (broken)
I wish it's 100% compatible to lsI keep `ls` un-aliased precisely because of this. I do keep these two aliases around:
alias l="eza --all"
alias ll="eza --long --all --time-style=long-iso --group"
Yeah that one's annoying.
I got used to a "recent" alias (Zsh):
if (( $+commands[eza] )) {
alias recent="eza --binary --octal-permissions --no-permissions --git -snew --icons=always"
} else {
alias recent="ls -rt"
}
For a long time now, I have wanted all command line utilities to consider options --exclude <regex> and --include <regex> options, where the regex refers to paths. This is applied before they do any displaying or evaluation.
So much more convenient than xargs.
À la powershell’s Get-ChildItems!
It’s a good point, as the shell glob syntax is too limited.
You can get something similar with shell globs, and ~not in zsh. e.g. *~*.c(.) to exclude all .c files (and only list files, not directories or anything else).
Looks a bit obscure at a glance due to lack of spaces, but it's not that different from -exclude or "| grep -v".
I just found this after I noticed support had stopped for exa.
Why is why I’ll never be using any of these as the default.
ls works, is not mission critical (you know what I mean), and will always be around.
Neat, it also works on termux, I like the tree output. Is there a parameter to just display the size, name and date format YYMMDD or rickdate for even shorter display, or can I hack it in the rust code? The permission and user column output distract me and take up space. With rust it can also be compiled to wasm and run on ios a-shell (which runs vim and python wasm and other smallish wasm's).
eza -l --time-style=+%Y%m%d --no-user --no-permissions
I will join others here to point out that information in readme is not presented the best way.
I am developer so I understand this, if you just take feedback from this post here and apply it, it will be much better.
- It is not fair to say ls is not maintained
- Clarify this is for of exa, I am familiar with exa, I wasn't sure what eza was.
- Give example how it can be used, alias ls="exa " for example, give few example of usage, not everyone is following your repo every day.
Thank you for work you've put into this.
It’s not saying that ls is not maintained.
How are people paging with these ls replacements? I wish with all the features it includes some guidance about which pager is suitable. more? less? something else? how does the pretty colors work with paging?
I use the --color=always option with eza. This allows it to be piped through less and still maintain the color.
To avoid having to type that option every time, I have a bash alias for ls:
alias ls='eza -F --color=always'
Not at three key strokes, it isn't!
`alias ls = "exa"`
Problem solved.
I am gonna pioneering using this as a drop in replacement for "ls". If i am not back in some days, remember me as a pioneer.
Btw good work, i always like modern gnu compatible tools
What happened to Exa?
Can definitely recommend eza (prev. exa). I've used it as an ls replacement for a long time with zero problems. If anyone's using nix home-manager, here's my config for inspiration:
programs.eza = {
enable = true;
# In list view, include a column with each file's git status.
git = true;
};
programs.bash.shellAliases = {
ks = "eza";
sl = "eza";
l = "eza";
ls = "eza";
ll = "eza -l";
la = "eza -a";
lt = "eza --tree";
lla = "eza -la";
};
Tangentially, does anyone know what happened to Ben Sago, the author of exa?
For people reading this and trying it for the first time and going through nix problems (well I did at least), check your distro package repo instead for eza. You probably already have it.
It looks like the nu-ansi-term crate hardcodes escape sequences. It would be more reliable to use terminfo or termcap as the sources of truth for which ones the tty supports.
This also works on Windows, fwiw.
Visually fancy, but personally it's way too "busy" for my brain.
I actually installed it a few days ago, which is rare for me, I tend to be restrictive to a fault with configuring my environment these days.
Happy so far.
Difftastic was another gem for me.
MIT - immediate nope from me for my gnu/linux stacks, but it seems well made and I wish you well!
Hints on bare ls, either GNU or BSD: - the -F flag give hints on items. Man ls. - never parse ls's output - color isn't always needed, see -F
I use lsd, because I like the name and it does what I want so far.
Nice tip. What got rid of most of my use of `ls` in fish was running `ls` automatically when you changed directories:
Seems like that would strongly encourage me to keep my directories tidier.
It absolutely did for me.
Sadly, it also serves as constant reminder that ~ is a bloody mess because people still can't get used to .local/.share/.config.
So it's OK to hide the mess, by throwing everything from the living room into the closet, I guess?
Not to mention, in the old days, that stuff was modtly in dot files.
(Users install graphical file manager. User has file manager set to bizarrely show dotfiles by default. User gets mad at prior hidden "clutter". Now dotfiles hidden one dir down.)
Yes? This is literally how every human in the world does it. You put your things, according to catrgories, into their respective room/cabinet. If somebody asks you where your sweaters are, you don't say "just search the ground", you say " in the closet".
Same thing here. You don't have to guess where files are, you know by convention.
My counterpoint was merely that ~/.<programname> hid things, unless you did weird things. Like explicitly ask to see all hidden things.
Having a file manager set to see all dotfiles by default, is like ripping all the doors off your closets.
You're completely missing the point.
~/.programname is an unorganized mess, where someone stuff their dirty laundry, their trash, their food and their passport into the same closet. It doesn't matter if the closet is open or not, nobody but the mentally ill hoarder who created the mess can navigate it.
~/.(local|share|cache) means people put their food in the fridge, their trash into the bin and their sensitive documents in a fire proof safe. Which means other people can take care of basic tasks like taking out the trash and creating backups of their sensitive documents.
The one thing I despise about local|share|config is I never know which one they're using or what kind of nested hierarchy they're using that means I might have to search for the company name first.
At least with the ~/.whatever system I can just start typing ~/.tool-name, hit tab and it'll show me the thing if it exists. If it's somewhere else I have to look it up.
It's not like ~/.whatever has ever been used consistently:
- ~/.mozilla/firefox, but: ~/.thunderbird and ~/.pki/nssdb (gonna keep you on your toes!)
- Java defaults to .full.package.name (on top of using .java, .openjfx, and others)
- Fontconfig uses `fc-*` for its tools. Naturally, its config file used to be in ~/.fonts.conf.d before they finally accepted standard directories
- arandr, as the name implies, uses .screenlayout
- The sooner the .net ecosystem decides if it wants to use ~/.dotnet or ~/.mono, the better (humble suggestion: ~/..net)
This really only applies to badly ported Windows software like Unity engine games. There should be no hierarchy, just ~/.{local/share,config,etc.}/$application And nothing stops badly behaved software from deciding to use ~/.$CompanyName or heck I have even seen ~/My\ Documents/$CompanyName
But that's disorganized!
I have a real filing cabinet. In it, I have folders.
I don't keep my backup car dongle in one folder, my car invoice in another, my warranty and info from dealer all in different folders. They're all in a folder with the car name on it.
The same for my fridge. The invoice, the manual, the warranty info, all in one folder.
It is much more disorganized to have a folder for manuals and put them all there. I have to find the one I want out of 50 such manuals. And if it is a warranty thing, then I need the invoice, and other papers.
Why would I want to keep associated things in different folders?!
You think it's a mess, but really it's not. It's organized for humans to find related things.
Before, I'd uninstall a program and delete its single dotdir. Done.
Now I have to hunt in a maze of madness to "get it all".
You cite some programs that didn't properly keep their data in a single dotdir, and use that as a reason why a single dotdir was bad?!
No. It's literally the other way around. It's bad that they keep everything in a single dotdir, because now I have to poke through dozens of folders to see where they hide their caches and other bloated garbage that shouldn't be backed up or kept in git, and where between all that garbage they're hiding their config files.
If all caches go to ~/.cache, I can exclude them all with a single setting, and I can put all my configurations in git/backups by adding ~/.config.
Same as with /var/tmp vs /etc vs /var/lib; if I want everything thrown together into a single folder I can just go use Windows.
~/.(local|share|whatever) means I have to search both the basement, the attic and the garage. For stuff i rarely need to touch so I forget every time where it was placed.
If it was only one place it would be great. If it was truly separated by config vs cache it would be great. The reality know though is that you have at least three locations where important config are stored, not counting those from package managers that have their own idea of this concept. Still, this mess is preferable to the even worse mess of hundred plumbing files spread on the living room floor.
I don't think it's all that weird, it's one of the first things I'd do in any file manager and I make sure Windows Explorer shows me system files too. If never had to interact with the hidden config it would be one thing, but I very often do and I don't want extra friction in getting to them.
Unsettling concept tbh
Taking this opportunity to remind folks: if you're going to emit a config file from your program, check for $XDG_CONFIG_HOME and use what you find by preference. ~/.config is a decent fallback. Sticking it in ~? It's not the 1980s anymore, please, don't.
Config files are the lesser problem, although it's really, really, really useful for programs to realize that $XDG_CONFIG_HOME exists.
More importantly, please put your caches under $XDG_CACHE_HOME so they don't trash up my backups or git.
And if you're feeling really fancy, put all your runtime stuff in a separate dir in $XDG_RUNTIME_DIR so /tmp doesn't look like someone detonated a zip bomb in there. I want to use it for my temporary files and still find them, thank you very much.
I'm one of those people... I don't want yet more hidden stuff in my home dir; I want less. My dream is to have zero hidden directories in my home. What I want is something really clean like this:
This is almost possible, thanks to XDG_ environment variables. But unfortunately many programs still use hardcoded names for the local userdirs.If you want to get closer to that goal, the xdg-ninja [0] package can help you. Also, do something like "touch ~/.local ; chmod 000 ~/.local" to force programs that use hardcoded names to fail spectacularly (instead of recreating the hidden dir).
[0] https://github.com/b3nj5m1n/xdg-ninja
I do the same in bash, but it's a bit wordier:
Goes well withNot strictly equivalent, but shorter (and should work with multiple shells):
$* will break on directory names containing spaces and other bash "word" delimiters, use "$@":
Oh cool idea! But gosh I think I would hate that.. I typically know what files are in directories that I'm working in, and usually care more about the output of previous commands I've run. I feel like this would teach me to never change directories
Also good practice
Neat idea, thanks! So obvious in hindsight... Just need to add some logic to it so it doesn't output more than N files.
For others (like me) who use zsh:
Ooo! Thank you! That is a nice tip! Stealing it right now. :)
For me, there are two principal cases of sorting in `ls` output: alphabetical when I'm trying to find something I don't know/ remember exactly, and mtime-based when I want to see the latest (or oldest) in a group of related files. I don't see how it could work with one shortcut.
Another thing is `ls -l` that's important when I need to understand file sizes and especially how symlinks are set up. Yet another is `ls -ld` which explains details about directories.
All these cases could be made more ergonomic, and maybe partly merged. But I don't see how I could compress them into one type of output that fits all purposes.
(My current fancy version of `ls` is `lsd`, but I still use the built-in `ls` a lot.)
To this end I made a simple script, `latest`, which is, essentially, `ls -lt $@ | head`.
So, `latest *.log`, etc.
Other than that, simple autocomplete does a lot of my ls work for me.
I know you're showing a rough example, but others might want to throw a `-d` in there so that folders don't get expanded. And put `$@` in quotations so spaced file names don't get interpreted as separate arguments.
i.e.:
edit: `-d` may be a bad choice. It also results in directories being listed first on my system, even with `-t` passed.edit 2: That was an alias I had setup. Carry on with the `-d`.
I cannot find this shortcut in https://fishshell.com/docs/current/interactive.html.
Do you know where it's documented by any chance?
It's there, in Shared bindings: "Alt+L lists the contents of the current directory, unless the cursor is over a directory argument, in which case the contents of that directory will be listed."
Ah, it was an L, I thought it was an I (eye). Thanks
Also many shells come with greatly improved ls implementations built in, like that of nushell.
yes, but the good thing is that you don't have switch shells with this. I'm running nushell on windows, which is nice, but I haven't got it as concise with $env.config.table.mode = "none", it also doesn't feature the tree display
I just use bash and tab tab all the time.
Yes! one full hand of mine is kept in reserve to keep hitting tab
Bash users: FYI you can bind shortcuts like this, too. I have my right hand home row keys bound to __bash_ctrl_n() (for e.g.), and various tools in my dotfiles override these functions (git, if installed, sets up __bash_ctrl_e() to run git status and git log).
Neat. Can you share the source of any of the functions you've bound to some of your keys?
In bash/zsh you can easily setup fzf completions ctrl-r (for directory) and ctrl-t (for shell history)
TIL! great tip, thanks. Now I just need to wire that shortcut up to `lsd` instead of `ls`.
Update: the ls command is stored at __fish_ls_command, so this is a `set -g __fish_ls_command lsd` in `config.fish`.
I just use mc and ctrl-O, to switch between shell and listing.
I realized most of my ls runs come right after `cd`, so I added these to my startup files. Now almost every `cd` does `ls` automatically:
history? atuin has been great.
In Bash you can also keep the history cleaner by adding ls (or other commands) to the HISTIGNORE env var: https://superuser.com/questions/232885/can-you-share-wisdom-...
I have been using fish for a long time and I didn't know about this. Thanks.
This appears to run eza for me, probably because I've aliased ls to eza. So I'm guessing it's just running `ls`.