return to table of content

Eza: A modern, maintained replacement for ls

alabhyajindal
46 replies
1d9h

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.

networked
24 replies
1d7h

Nice tip. What got rid of most of my use of `ls` in fish was running `ls` automatically when you changed directories:

  function ls_on_cd --on-variable PWD
      ls
  end

macintux
16 replies
1d6h

Seems like that would strongly encourage me to keep my directories tidier.

creshal
15 replies
1d5h

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.

bbarnett
11 replies
1d4h

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.)

wadim
10 replies
1d3h

So it's OK to hide the mess, by throwing everything from the living room into the closet, I guess?

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.

bbarnett
9 replies
1d3h

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.

creshal
6 replies
1d2h

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.

chippiewill
2 replies
1d2h

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.

creshal
0 replies
1d1h

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)

account42
0 replies
4h0m

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.

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

bbarnett
1 replies
23h57m

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?!

creshal
0 replies
21h15m

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.

Too
0 replies
23h48m

~/.(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.

xelamonster
0 replies
1d3h

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.

NetOpWibby
0 replies
1d3h

Unsettling concept tbh

samatman
1 replies
1d2h

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.

creshal
0 replies
21h13m

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.

enriquto
0 replies
22h53m

people still can't get used to .local/.share/.config

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:

    $ ls -a ~
    . .. config fun local pro tmp
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

tutipop
2 replies
1d1h

I do the same in bash, but it's a bit wordier:

  _chpwd_hook() {
    if [[ "$PWD" != "$PREVPWD" ]]; then
      ls
      PREVPWD="$PWD"
    fi
  }

  PROMPT_COMMAND=(_chpwd_hook)
Goes well with

  shopt -s autocd
  alias r='cd -'

mbivert
1 replies
1d

Not strictly equivalent, but shorter (and should work with multiple shells):

  $ cd() { builtin cd $* && ls; }
  $ cd /
  bin  boot cdrom  dev  etc  home  lib  lib64 [...]

oxygen_crisis
0 replies
22h14m

$* will break on directory names containing spaces and other bash "word" delimiters, use "$@":

    cd() { builtin cd "$@" && ls; }

ktm5j
1 replies
1d5h

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

idunnoman1222
0 replies
1d1h

Also good practice

diggan
0 replies
1d2h

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:

    function chpwd() {
      ls
    }

blooalien
0 replies
1d7h

Ooo! Thank you! That is a nice tip! Stealing it right now. :)

nine_k
3 replies
1d4h

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.)

whartung
2 replies
1d2h

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.

jmholla
1 replies
1d1h

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.:

    ls -ltd "$@" | head
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`.

zokier
0 replies
1d

    find -type f -printf '%M@ %p\0' | sort -zn | tail -z | sed -z 's/^[0-9.]* //' | ...
Ugh.. so unixy

ognyankulev
1 replies
1d8h

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."

jiehong
0 replies
1d7h

Ah, it was an L, I thought it was an I (eye). Thanks

tormeh
1 replies
1d9h

Also many shells come with greatly improved ls implementations built in, like that of nushell.

fsiefken
0 replies
1d8h

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

nolist_policy
1 replies
1d8h

I just use bash and tab tab all the time.

FergusArgyll
0 replies
1d4h

Yes! one full hand of mine is kept in reserve to keep hitting tab

000ooo000
1 replies
1d8h

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).

jmholla
0 replies
1d2h

Neat. Can you share the source of any of the functions you've bound to some of your keys?

sva_
0 replies
1d

In bash/zsh you can easily setup fzf completions ctrl-r (for directory) and ctrl-t (for shell history)

samatman
0 replies
1d2h

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`.

oneshtein
0 replies
1d5h

I just use mc and ctrl-O, to switch between shell and listing.

mixmastamyk
0 replies
21h42m

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:

    # bash, simple
    function cd() {
        builtin cd "$@" && ls -l
    }

    # fish, a bit more sophisticated
    function cd

        builtin cd $argv;
        if test $status -gt 0  # there was an error, stop
            return
        end

        # auto print dir info
        if test "$argv" != ""  # not home though
            dir  # aka ls -l ...
        end
    end

latchkey
0 replies
1d2h

history? atuin has been great.

Osiris
0 replies
15h51m

I have been using fish for a long time and I didn't know about this. Thanks.

Macha
0 replies
1d4h

This appears to run eza for me, probably because I've aliased ls to eza. So I'm guessing it's just running `ls`.

godshatter
29 replies
1d1h

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.

dlivingston
19 replies
1d1h

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.

fngjdflmdflg
13 replies
1d1h

You can hover over the date for an exact timestamp. Maybe someone can write a userscript to replace the relative dates to exact ones.

fuzztester
3 replies
21h30m

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.

buzzerbetrayed
1 replies
19h28m

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.

teytra
0 replies
9h13m

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.

michaelcampbell
0 replies
5h50m

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.

igorguerrero
2 replies
1d1h

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?

reillys
1 replies
1d1h

Well it will definitely help with caching. You only need to update the article every year or so.

fngjdflmdflg
0 replies
1d

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."

elashri
2 replies
1d

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); }); })();

fngjdflmdflg
1 replies
1d

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;})

fngjdflmdflg
0 replies
20h40m

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))

TylerE
1 replies
1d

Can’t hover on mobile

sva_
0 replies
1d

You can hover with a pen like the Galaxy S Ultra has. But it doesn't work.

godshatter
0 replies
1d1h

Huh, I never noticed that. There is a lot of sublety in HN's minimal formatting.

bangaladore
1 replies
23h59m

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"

creshal
0 replies
2h26m

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!

fuzztester
0 replies
21h37m

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.

TheBengaluruGuy
0 replies
1d1h

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

wocram
1 replies
23h41m

This is a setting, you can change it to any other date format you want.

SAI_Peregrinus
0 replies
23h33m

Yep, `--time-style`.

tjoff
1 replies
1d1h

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".

pas
0 replies
17h14m

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.)

hhh
1 replies
1d1h

You can hover over the time on HN and get a timestamp.

tirpen
0 replies
23h55m

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.

quirino
0 replies
1d1h

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...)

keybored
0 replies
22h41m

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

fuzztester
0 replies
21h32m

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.

sandreas
20 replies
1d

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 fun

thiht
9 replies
1d

4 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

theshrike79
5 replies
20h33m

Task is _amazing_

I tried magefiles[0] for a while, but Task just works so much better and isn't Go-specific as heavily.

[0] https://github.com/magefile/mage

sweeter
3 replies
19h43m

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.

lelanthran
2 replies
3h22m

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.

thiht
1 replies
1h50m

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 .

lelanthran
0 replies
43m

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:
          - ...

thiht
0 replies
20h15m

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.

sandreas
0 replies
23h45m

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

rwmj
0 replies
23h23m

hyperfine is absolutely brilliant. My go-to replacement for time.

kstrauser
0 replies
22h37m

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.

magarnicle
2 replies
19h37m

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.

lilyball
1 replies
18h44m

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.

magarnicle
0 replies
16h5m

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.

sandywaffles
1 replies
1d

I use du-dust over gdu, but otherwise my list is almost identical to yours.

sandreas
0 replies
23h45m

Thanks. I will definitely try that out.

satvikpendem
0 replies
9h32m

Gotta love Rust (in which most if not all of these tools are written).

heavyset_go
0 replies
19h4m

As someone who defaults to lsd, is there any reason why you prefer eza to it?

gkfasdfasdf
0 replies
22h32m

Great list! I would also add:

   viddy, a replacement for watch that includes history

Tor3
17 replies
1d9h

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.

brabel
3 replies
1d6h

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?

z2h-a6n
0 replies
1d4h

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

skydhash
0 replies
1d4h

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.

drdo
0 replies
9h4m

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.

MatthiasPortzel
0 replies
1d3h

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.

scns
4 replies
1d9h

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.

kibwen
2 replies
1d6h

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).

sshine
1 replies
1d6h

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.

fwip
0 replies
1d1h

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.

Narishma
0 replies
1d2h

It's not easy on my eyes. It looks washed out with too low contrast.

samatman
0 replies
1d2h

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.

oneeyedpigeon
0 replies
1d6h

30-odd years of using ls and this comment is finally the catalyst for me to start using -A instead of -a. Thank you!

jiehong
0 replies
1d9h

--color=never

ducktective
0 replies
1d3h

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.

[1]: https://github.com/sharkdp/vivid/

Tyriar
0 replies
22h37m

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".

daghamm
14 replies
1d7h

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?

coffeeri
6 replies
1d7h

I think they are not referring to ls, but to exa [0], which is not maintained anymore.

[0]https://github.com/ogham/exa

Izkata
5 replies
1d5h

No, they definitely mean "ls":

By deliberately making some decisions differently, eza attempts to be a more featureful, more user-friendly version of ls.
coffeeri
2 replies
1d5h

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.

lynndotpy
0 replies
1d

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`:

- https://crates.io/crates/eza

- https://crates.io/crates/exa

kazinator
0 replies
1d2h

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.

cafkafk
1 replies
1d4h

We do not

verdverm
0 replies
1d3h

A modern, maintained replacement for ls.

The tag line certainly reads that way

(first line in the readme)

hparadiz
2 replies
1d7h

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.

linkdd
1 replies
1d7h

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.

Gormo
0 replies
1d6h

Or dynamically-linked binaries that are distributed via containers.

kazinator
1 replies
1d2h

Because he's deliberately confusing "maintained" with "actively developed" in order to insinuate that the existing tools is unmaintained.

linkdd
0 replies
1d2h

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...

nine_k
0 replies
1d4h

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.

ducktective
0 replies
1d3h

Professional Linux masters just use the `echo *` shell built-in

tmountain
11 replies
1d5h

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).

jen20
2 replies
1d4h

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…

qorrect
1 replies
1d

What is 'sl' ?

L3viathan
0 replies
1d

Steam Locomotive, an annoying little ASCII art film to punish you for typos. Funny exactly once.

FuckButtons
1 replies
1d1h

You can alias it to whatever you want though.

DSMan195276
0 replies
23h31m

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

redxtech
0 replies
13h43m

`command -v eza >/dev/null && alias ls="eza"`

glandium
0 replies
20h43m

This is where an azerty keyboard shines.

elendee
0 replies
14h51m

this was my first reaction too

cafkafk
0 replies
1d4h

I was a former exa user, and the z is next to x on my keyboard, wasn't a huge hassle for me

acupofnope
0 replies
1d5h

Can you elaborate on why aliasing is kind of weird?

F3nd0
0 replies
1d3h

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.)

kazinator
11 replies
1d2h

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.

elashri
9 replies
1d2h

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.

ehutch79
8 replies
1d1h

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

ehutch79
2 replies
1d1h

Side note: the English language is a dumpster fire, and it’s easy for these issues to happen.

kazinator
0 replies
1d

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.

crazygringo
0 replies
1d

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.

wffurr
1 replies
20h13m

Don’t comment based on just the title, please.

kazinator
0 replies
19h53m

I clicked through the title, but mostly looked at code and example invocations and output.

timeon
0 replies
22h48m

Yes title is not clear so parent was just clarifying.

elashri
0 replies
1d1h

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.

L3viathan
0 replies
1d

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.

dvektor
0 replies
1d2h

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.

JonChesterfield
7 replies
1d5h

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.

hibbelig
2 replies
1d5h

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.

st_goliath
1 replies
1d5h

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.

gumby
0 replies
1d4h

For GNU ls: e/E, j/J, V, K, M, O, P, W, y/Y and z are not used

Challenge accepted!

WesolyKubeczek
1 replies
1d5h

emphasis on community building

Probably the first time ever I hear about a community built on a freaking directory listing tool.

jauntywundrkind
0 replies
1d4h

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.

zokier
0 replies
1d

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

creshal
0 replies
1d5h

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.

dsjkvf
6 replies
1d8h

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?

jen20
3 replies
1d4h

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.

[1]: https://www.shellcheck.net/wiki/SC2045

alerighi
2 replies
19h4m

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.

xigoi
0 replies
9h4m

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?

jen20
0 replies
13m

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.

oneeyedpigeon
0 replies
1d6h

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.

jryb
0 replies
1d8h

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.

jm4
3 replies
1d1h

What’s with all these new versions of GNU utilities being built with the MIT license? Seems like there are a lot of them.

mprovost
0 replies
20h59m

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.

Arnavion
0 replies
1d1h

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.

gkfasdfasdf
3 replies
1d

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.

ttyprintk
2 replies
12h16m

Totally —- any idea why eza claims exa doesn’t support it? I know that’s wrong.

gkfasdfasdf
1 replies
3h36m

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.

ttyprintk
0 replies
2h45m

Ah, good point.

felixr
3 replies
1d9h

I find it strange that the README does not mention at that `eza` is a fork of `exa`.

cafkafk
1 replies
1d4h

contributions welcome

soraminazuki
0 replies
23h37m

Crediting people becomes awkward when it's done by outsiders though.

n8henrie
0 replies
3h2m

eza features not in exa (non-exhaustive):

It at least mentions it's existence (though no link or context)

_flux
0 replies
1d3h

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.

srid
0 replies
1d2h

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.

synergy20
2 replies
1d4h

    ls -lrt
    eza -lrt (broken)
I wish it's 100% compatible to ls

WhyNotHugo
0 replies
18h59m

I 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"

AndyKluger
0 replies
1d4h

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"
  }

sriram_malhar
2 replies
1d9h

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.

jiehong
0 replies
1d7h

À la powershell’s Get-ChildItems!

It’s a good point, as the shell glob syntax is too limited.

arp242
0 replies
20h54m

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".

zeristor
1 replies
1d9h

I just found this after I noticed support had stopped for exa.

isatty
0 replies
1d7h

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.

fsiefken
1 replies
1d8h

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).

e38383
0 replies
1d7h

eza -l --time-style=+%Y%m%d --no-user --no-permissions

desireco42
1 replies
1d1h

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.

xigoi
0 replies
9h2m

It’s not saying that ls is not maintained.

barkingcat
1 replies
21h21m

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?

timmytokyo
0 replies
18h16m

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'

AlchemistCamp
1 replies
4h14m

Not at three key strokes, it isn't!

gaws
0 replies
59m

`alias ls = "exa"`

Problem solved.

tcsenpai
0 replies
1d6h

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

quasarj
0 replies
1d

What happened to Exa?

phlip9
0 replies
23h52m

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";
    };

kseistrup
0 replies
1d7h

Tangentially, does anyone know what happened to Ben Sago, the author of exa?

kristopolous
0 replies
1d7h

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.

erik_seaberg
0 replies
13h23m

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.

dflock
0 replies
1d4h

This also works on Windows, fwiw.

deskr
0 replies
1d9h

Visually fancy, but personally it's way too "busy" for my brain.

codr7
0 replies
20h23m

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.

arminiusreturns
0 replies
1d1h

MIT - immediate nope from me for my gnu/linux stacks, but it seems well made and I wish you well!

anthk
0 replies
1d

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

INTPenis
0 replies
22h15m

I use lsd, because I like the name and it does what I want so far.