1. 43
  1.  

  2. 26

    exa is written in Rust, so it’s small, fast, and portable.

    -rwxr-xr-x  1 root      wheel    38K 28 Apr 20:31 /bin/ls
    -rwxr-xr-x@ 1 curtis    staff   1.3M  7 Jul 12:25 exa-macos-x86_64
    

    ?

    1. 9

      Stripping it helps a bit… but not much though.

      $ du -hs exa-macos-x86_64  
      1.3M	exa-macos-x86_64
      $ strip exa-macos-x86_64     
      $ du -hs exa-macos-x86_64  
      956K	exa-macos-x86_64
      

      More fun is what it links to:

      $ otool -L /bin/ls            
      /bin/ls:
      	/usr/lib/libutil.dylib (compatibility version 1.0.0, current version 1.0.0)
      	/usr/lib/libncurses.5.4.dylib (compatibility version 5.4.0, current version 5.4.0)
      	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1238.60.2)
      $ du -hs /usr/lib/libutil.dylib /usr/lib/libncurses.5.4.dylib /usr/lib/libSystem.B.dylib
       28K	/usr/lib/libutil.dylib
      284K	/usr/lib/libncurses.5.4.dylib
       12K	/usr/lib/libSystem.B.dylib
      $ otool -L /tmp/exa-macos-x86_64
      /tmp/exa-macos-x86_64:
      	/usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
      	/System/Library/Frameworks/Security.framework/Versions/A/Security (compatibility version 1.0.0, current version 57740.60.18)
      	/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1349.8.0)
      	/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.8)
      	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1238.60.2)
      $ du -hs /usr/lib/libiconv.2.dylib /System/Library/Frameworks/Security.framework/Versions/A/Security /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation /usr/lib/libz.1.dylib /usr/lib/libSystem.B.dylib
      1.6M	/usr/lib/libiconv.2.dylib
      9.3M	/System/Library/Frameworks/Security.framework/Versions/A/Security
      9.7M	/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
       96K	/usr/lib/libz.1.dylib
       12K	/usr/lib/libSystem.B.dylib
      
      1. 6

        To be fair, exa is a self-contained executable, while ls probably has a dependency to libc, which it loads dynamically. If Rust ever becomes very popular and its runtime is installed by default everywhere, its executables will also be a few KB only.

        1. 4

          FWIW, linking ls from GNU coreutils statically with musl-libc on x86_64 gave me a 147K ELF with no shared object dependencies.

          1. 3

            For that to be true Rust would have to have well defined and stable ABI. Which it doesn’t have right now.

            1. 3

              Rust binaries actually do dynamically link to libc. Its standard library, which calls libc, is statically compiled into binaries.

          2. 21

            Here’s a fun thing: I downloaded and tried the Linux version on Fedora and here’s what I get.

            exa: error while loading shared libraries: libhttp_parser.so.2.1: cannot open shared object file: No such file or directory
            

            Gone are the days where command line utilities were simple and self-contained. Now you need an HTTP parser to list files on your filesystem. I guess we’re in post-NPM era.

            1. 7

              Appears to be a known bug.

              Following the chain of links there: exa depends on libgit2 in order to provide the git status of files, which is entirely a local operation. And libgit2 has some feature flags to support this type of usage; exa turns off all the optional features (threads, https, ssh) to avoid compiling in stuff it doesn’t need. This successfully removed a dependency on openssl (!) that earlier exa builds included. But even with feature flags off, libgit2 seems to still depend on curl, which depends on libhttp_parser.

              1. 6

                But not to worry. Software isn’t too complex. We totally understand everything that’s going on.

              1. 1

                Oops. I thought it was vaguely familiar.

              2. 11

                I really dislike that “modern” is nowadays used as a synonym for “good”. It tells nothing about the project itself.

                1. 11

                  I read “modern” as “built with extended attributes, colour terminals and large files in mind”. That is, it needn’t be a judgement of quality; rather, a description of design considerations.

                  1. 12

                    ls(1) had 2 of those 3 features for 20 years. Color output was added to GNU coreutils ls in 1996, human readable sizes in 1997. Just because you reimplement something doesn’t mean the idea is suddenly “modern”

                    1. [Comment removed by author]

                      1. 2

                        Was an alias so hard?

                        1. 1

                          Remembering to unset is hard, or use command, becausr there’s no quick obvious to get human-unfriendly units with -h :/

                          (Better make a new tool than submit a patch. /s)

                          1. 1

                            Prepend an ‘\’ to the command, and the alias substitution gets skipped.

                    2. 8

                      Sometimes it just feels like it means “rewritten in Node.JS or Golang”.

                    3. 19

                      I find the implication that something being old is somehow inferior frustrating as well.

                      1. 4

                        I’ll just keep reading it as a synonym for “young.”

                      2. 4

                        For example, exa prints human-readable file sizes by default (when would you not want that?)

                        Um, fairly frequently, actually – knowing the exact-to-the-byte size of a file (or a few files) can be quite useful.

                        1. 13

                          I think their point is that the default output for a tool such as ls or exa should be human-readable.

                          Humans are uaully the ones who don’t like extra typing. I don’t often hear computers complain about that :p

                          If you’re automating something, you can probably read the manpage and figure out that there’s a -B flag to get file sizes in bytes if that’s something you need, but I think most people would find 946831165B much more difficult to conceptualize than 946MB.

                          1. 3

                            Sure – my point was that non-“human-readable” file sizes are not completely useless, as the parenthetical in TFA seems to be trying to imply.

                        2. 3

                          It seems vaguely similar to ls++.

                          1. 2

                            Useful tool, I would like to replace my ls(1) even without git support. Why I use exa git support when I can simply running a git status :)

                            1. 2

                              To say replacement instead of alternative is strange because you would expect a utility like ls to be as generalized as possible and building in features like Git is a bit much.

                              1. 1

                                Baked in git support seems like a terrible idea. It would be much better to have some sort of a plugin hook so that developers could add support for whatever they want.

                                1. 1

                                  like a shell script wrapping it ? :^)

                                2. 1

                                  Cool, I wonder how easy it is to add support for other vcs? Ideally in a way that wouldnt bloat it