Hacker News new | past | comments | ask | show | jobs | submit login
Sl: a mirror version of ls (gir.st)
165 points by fredrb on Mar 30, 2018 | hide | past | web | favorite | 121 comments

Probably an unpopular opinion, but I find aliases and extensive dotfiles counterproductive.

It's better to learn and remember the exact commands. If you find yourself typing the same long command over and over again, the task should probably be automated or scripted as part of a separate pipeline.

Assuming you are successful with aliasing and don't accidentally do something unexpected and catastrophic to your system, the moment you login to another system you will be lost and unable to remember any of the original and core commands.

There are plenty of cases where it can be unproductive, but I find it very helpful in some cases.

I find `alias gcr="git clone --recursive"` to be very productive for me. I never forget what it stands for, it saves me time, and I never have to go fetch all submodules if the repo uses them. `alias lt=ls -tor` is helpful, as it shows me extra information about files in reverse sorted order, so that the most recently modified files are at the bottom.

I don't run any risk of forgetting either of these because of their mnemonic nature, and they're not something I can script.

I was of the same opinion as the GP until I started using Terraform. Coming from a sysadmin background, I was always told to use default tools 'because one day you'll ssh into a random server and it won't have any of your fancy tools and config'.

So I started using Terraform. A lot. Day in, day out, I would type terrafrom, teraform, terrafomr. And I'm a good typist! But something about that word just makes it hard to get out right. (I have a similar issue with 'infrastructure'.)

Finally replacing it with a 'tf' alias saved me a lot of frustration.

This is actually supporting GP's argument.

Why do you have to "type" terraform? Are you running terraform from your own machine? Don't. Setup a Jenkins pipeline or what have you. Unless you happen to work alone – and I'd argue even then.

Moving Terraform to Jenkins was the second best thing we have ever done – first thing was moving tfstate to remote storage.

You can provide any required parameters (or jenkins can fetch for you), run terraform init, plan, ask for confirmation, apply (and even perform retries). And then run any post steps. Even managers can use terraform now (and we have a pretty complicated setup).

I guess only Terraform Enterprise might beat this, but I have little experience with that.

This is a great way to go, but I think you're actually asking GP to have his cart before his horse. This is how I learned and how you learned, I'd guess... by typing the command into a terminal. Am I being luddite? I had to be dragged kicking and screaming to set up CI for my product's tests, but I see the value of it now.

How many thousands of times should you type "terraform" in full before you're comfortable with all of the nuances of syntax and command-line arguments? (Or kubectl --namespace=kube-system get pods, or git pull --rebase origin master for that matter)

And if these managers who couldn't use Terraform before, can use it now, but also require someone to set up a Jenkins job for them...

I'd just be sorta worried that they might get the idea this tool could only be run with adult (Root-type) supervision, because I've seen it happen like this so many times.

(I'm sure it's better than the alternative, which is a world in which managers can't or won't ever learn to run this tool at all, simply because it requires use of a command-line.)

Just curious do you use Terragrunt or something like it? Or does the fact that Jenkins only allows a single job to run once concurrently actually obviate the need for that... I'm not using Terraform (but wish I was) although I've got a basic Jenkins setup for some CI things on my less than 10-person product team.

To be fair I think you may have just convinced me that I need to be able to do this too. I actually have a Jenkins server and we use it for CI to run our product's test suite by hand, but not much else. We have a team that provisions EC2 resources, we have a team that handles security rules, and everyone is a competent professional but sometimes as a developer the appearance from the outside of that group is that a left hand does not know what the right hand is doing.

I guess with Jenkins and a remote tfstate, you make it very easy to know who owns what resources, and to see who has done what, or even specifically which locks are actually open and what resource is currently in motion.

We ran Terraform in Bitbucket Pipelines builds - full testing with awspec, remote state in S3, statefile locking in DynamoDB.

It might surprise you, but there are cases where you might not want to run Terraform in a pipeline.

What is this awspec? I would like to subscribe to your blog or mailing list!


Haha I don't have either, I'm afraid. Here's a link to the common architectures I helped out on when I was at Geoscience Australia: https://bitbucket.org/account/user/geoscienceaustralia/proje...

Here's a direct link to the awspec tests for one of the repositories: https://bitbucket.org/geoscienceaustralia/webserver/src/ab6f...

I've got only 2 shortcuts I use all the time. 'r' = rsync -vrlHpogDtSx --numeric-ids --progress And a small python script '2' that allows me to ssh into any system within 4-6 keystrokes (even doing tty tricks to not require <enter>).

Thats why I write my code without any libraries or frameworks.

Sarcasm aside, you are correct but it’s better to learn things first. But after a while, those aliases and dotfiles are just shortcuts. I’ve had my dotfile repo with things I need for something like 8 years and hasn’t changed much beside vim plug-in updates and I could just whip up the same setup manually but it would take a half a day to get everything to how I prefer things. They just save time and sanity.

Your principle holds: it's always better, when exploring a new field, to start without try the most minimal libraries and frameworks after you already experience the pain they solve.

Why do you think it's good to put a long command in a script, but bad to make it an alias? It sounds like you think shell dotfiles can't be managed across machines just like script files.

That isn't exactly what I wrote, but I'll still try to answer your question.

An alias is only going to be available to the current shell and it's going to be stored in memory. A script is going to be accessible to the entire system and stored on disk.

In the majority of my use-cases I require shipping software to production systems and my scripts are used to manage production services. The last thing I want to do is having to manage aliases on multiple systems ( some of which I do not own ).

To me the difference between a script and an alias is too trivial to quibble over. I'm fine putting all of my aliases into one-line scripts, if that would really make them easier to manage across systems.

My basic philosophical disagreement is with the idea of avoiding interactive command shortcuts. This essentially limits you to only using command line features you can memorize, or be willing to look them up every single time. There are too many commands, with totally inconsistent argument styles, for this to be practical.

The result is that you're only going to use a small subset of the command line's power if you limit yourself in this way.

RANT: Yes, I agree alias ll="ls -l" is a crutch. But why does 'sort' use -t for separator and -f for field, while 'cut' uses -d and -k? The famously composable Unix tools really aren't very consistent. Radically improved tab completion and documentation (vs man pages and Info) might be a start, but in the end you have to evolve new syntax.

Sort uses -t and -k, cut uses -d and -f. Your point is valid, of course - the options are not consistent across the unix tools.

Thank you, I can't even keep track of the option names for long enough to properly curse them. I wonder if there could be a kind of POSIX schema for similar options across utilities, such as

-o fieldseparator=,

-o fieldkeys=2,1,3

which could be used by any program whose capabilities require such a specifier, could be parsed from config files and environment variables, and aliased for reduced verbosity.

Personally - I write aliases locally that I know I don't need/can live without remotely (e.g. "vi" aliases to "vim" because sometimes I fail to get that "m" on there and I want vim but only on my laptop), I can't imagine writing "system-wide" things as an alias without losing some sleep.

I'd agree with the concept of memorizing it in theory but I'm with you that it becomes a bit too much when the tooling differences in switches from command to command can be even minimally different (something as simple as scp "-P" vs ssh "-p" is easy to forget in the moment). Yeah, I can memorize that example but everything has flags for everything and they can be vastly different (like you mentioned sort vs. cut)

Unsolicited opinion on this: she'll scripts are great for adding documentation to commands. I've got a lot of 2-5 line scripts that just remember the right commands for me.

Aliases I only use as direct abbreviations of the underlying command.

Counterpoint: My git workflow. I commit often and I commit a lot. For this there are a few but quite long commands that I use over and over and over again.

I turned all of them into two-letter aliases.

It’s perfect!

Here is a direct link to the line in question of my bashrc:


I recently put my dotfiles on GitHub. As you can see from the above linked file, my bashrc is short and sweet.

Thes dotfiles were, counter to what one might think given how few and short they are, not thrown together in short time.

These dotfiles reflect the specific workflow I’ve developed for myself over years of using FreeBSD, Linux and another couple of Unices.

In the beginning my dotfiles were long and messy and they accumulated a lot of cruft that I never used. That’s why I didn’t use to have them on GitHub. But over time I cut them down to only the things I actually used. The end result was that my entire bashrc is authored by myself for myself with nothing copy-pasted from the Internet.

That’s the secret to successful aliases as well IMO — make aliases where it really matters. Then you’ll only have a few, which in turn makes it easy to navigate systems where you don’t have your full set of dotfiles.

My git aliases are very important to me, but since there are only a handful of them and I almost don’t alias anything else, I can easily type them onto new systems by hand if need be.

I find aliases and extensive dotfiles counterproductive.

The first thing I do on a new machine is tweak my profile to alias 'cp', 'mv' and 'rm' to prompt me before performing destructive operations, and to be verbose about what they're doing. Doing this has saved me from myself several times. While I'm there I usually also set 'ls' to use colored output, since I like to have an easy at-a-glance way to know what it's showing me.

The second thing I do is tweak the prompt to include the current time, so I can scroll back and find out when I did things, or see how long things took without having to use explicit timing commands. Doing this has also been helpful on multiple occasions.

After that I go set EDITOR, set HISTCONTROL how I want it, and usually set up a couple other files which get sourced by the main profile, in order to set up tool- or API-specific env stuff.

This does end up producing a fair bit of stuff in those "dotfiles" you dislike, but I find it to be a quite useful approach.

This is actually one of the primary reasons I haven't gotten into Emacs. To get the most out of it requires customization to its startup config. But I spend most of my time on random servers I support, which won't have my custom configs on it.

Now what would be really nice is to have config forwarding built into ssh, similar to how ssh key agent forwarding works.

I do maintain some level of vim knowledge for when I'm on strange systems. But it's not hard to install my emacs config so if I'm going to spend significant time on a system I will do that.

But if you can ssh in, you could just tramp on your local emacs to edit files remotely. It's quite magical.

In my case, I have to support a large number (500 or so) Linux boxes that are hosted at customer sites (for a custom middleware-type application). And the remote access they have provided for us isn't a direct ssh connection, it goes through a web based gateway using an old active-x control, and embedded shockwave/flash based app (yes, yuck). I'm in the process of replacing that now.

How does infrastructure like that ever happen? Reading that made me feel slightly ill.

I just use tramp to edit files remotely in emacs. Works reasonable well.

I agree to a certain extent. Definitely aliases.

But, for your main tools, if dot files can make a difference then you should make an exception.

Vim without my .vimrc is almost a different apps, and I'm way less efficient without it!

I agree that certain dotfiles can be fairly useful.

I'm not using Vim, but I do keep configuration files for my local text editor.

I'm not sure I see the difference between having your text editor configured vs. having your shell configured. My shell is my primary interface to my computer and I spend at least as much time interacting with it as I do my text editor. I just don't see the advantage of leaving it un-configured. You must jump systems much more often than I do.

I agree that it can be an anti-pattern.

However there is stuff like this:

alias ec2ls='aws ec2 describe-instances --query '\''Reservations[].Instances[].[Tags[?Key==`Name`].Value|[0],State.Name,InstanceId,PrivateIpAddress,PublicIpAddress]'\'' --output text | column -t | sort'

I could try to remember it and type every time. But why? Sometimes all I want to do is list instances and grep for something quickly. If I can 'ls' for files, why would 'ls' for AWS (or openstack or what have you) be any different?

What's with all the top level comments talking about aliases? Are you commenting on sl or actually replying to other comments?

My aliases and dotfiles are a cheap form of documentation.

Absolutely this!

I always liked the story about the guy who aliased emacs to be 'em'. Until one day he accidentally typed an 'r' instead of an 'e'. It turns out aliases can cost a lot more time than they can save!

If he would just had an alias of rm to `rm -i`...

I can't imagine needing to alias emacs. Maybe emacsclient, if you're not just doing everything from a shell in emacs.

I like to add "install https://github.com/mtoyoda/sl" to my companies "Getting started" documentation to prank new hires. Great fun!

I was hoping someone posted this, if not I was going to. I installed it on one of my home servers YEARS ago, and forgot about it until a couple years later I typoed "sl" and it chooched across my screen. I howled with laughter at it, and at setting myself up years in advance.

If I have sudo access on a friends machine, installing Steam Locomotive is generally the first thing I do. Adding it to the "Getting started" docs at my company does sound like a good idea.

Remove the trailing double-quote from the above URL to get to the intended destination.

Or you just

    alias sl=ls
and have productivity reach unseen levels!

I've had "l" aliased to "ls -lhp" for so long that I can't work properly without it. I think many distros also alias "ll" to "ls -l" by default (I think CentOS/RHEL does it at least).

    alias l="tree --dirsfirst -ChFL 1"
    alias l2="tree --dirsfirst -ChFL 2"
    alias l3="tree --dirsfirst -ChFL 3"
    alias l4="tree --dirsfirst -ChFL 4"
    alias l5="tree --dirsfirst -ChFL 5"
( or https://github.com/ogham/exa in tree mode )

I, too, have "l" aliased, but years of muscle memory I still type "ls -lahp" every single friggin' time. Hey, at least it's portable when I'm ssh'd to another system.

I have h=ls and hh=ls -l, which are much more comfortable with the Dvorak keyboard layout. (The equivalent would be j and jj on Qwerty.)

I aliased d instead. I also have ll and la but I don't use them that often so didn't change them to be Dvorak optimized.

Good idea. Dvorak users unite!

Do you use regular dvorak or programmer dvorak?

British Dvorak, since it keeps ", £, # etc where I expect them, but is still a standard layout available on Linux and Mac.

I have l aliased to -lhrt since it’s what I mostly need.

I have a few "idiot aliases" like that...

  alias grpe=grep
  alias gerp=grep

> grpe

Every. Single. Time. Sometimes I even typo it many times in a row.

There must be //something// in that combination of letters, because I don't recall ever having that many mistakes with any other commands.

I think that many of my typos occur when switching between letters on one hand vs the other. I figure it's a brain hemisphere synchronization thing.

    alias gti='/usr/local/bin/git'
    alias gut='/usr/local/bin/git'

My personal favorite is:

   alias fuck='sudo $(fc -nl -1)'
Be very careful with this.

Here's one of my aliases for you:

    function fuckgit
        rm -rf /tmp/fuckgit/
        git clone --no-checkout (git config --get remote.origin.url) /tmp/fuckgit/
        rm -rf .git/
        mv /tmp/fuckgit/.git .
        rm -rf /tmp/fuckgit/

What about the actual program thefuck? It can fix more than just sudo, and asks you to confirm

I don't want to be asked and I don't want to install anything.

I looked at thefuck but it didn't seem to do anything I needed.

Or make history work for you:

  shopt -s histverify histreedit
Bash will let you then confirm the actual command it's going to run:

  sudo !!

I use zsh and I don't know what shopt is. That's two commands and !! doesn't work in aliases.

In zsh it is called setopt. You don't need to make an alias, you would put this in your .bashrc

So why not just type 'sudo !!' ?

Because it isn't as much fun.

I think you can try this. https://github.com/nvbn/thefuck

I generally have this in my bash_aliases

    alias ls='ls -lah --color="auto"'
    alias l='ls -lah --color="auto"'
    alias ll='ls -lah --color="auto"'
    alias sl='ls -lah --color="auto"'

For some reason the typo I tend to make the most is ';s', so I've gone ahead and set `alias s=ls`

I mean, yeah, you could, but that's not as much fun.

I've set alias ls=sl in dozens of systems belonging to colleagues over the years, just for the lulz! :D :D

This program reverses the output.

alias lsd="ls -d */"

I once installed sl on a server. Completely forgot I put it there. It laid there dormant for MONTHS without anyone tripping over it. Then....it happened.

"What the...why is my screen blac--is that a train-AW DAMMIT".

That person was me. The guy who installed the damn thing.

The progression from confusion, to curiosity, to realization that I had in fact...just played myself was kind of amusing in the moment.

As a golf owner, lol

No no no. There is only one 'sl'.


Thank you. You made my day! :D I'm confident that there are other such commands that I'm unaware of and don't know how to find them. May be you could help out.


Faced with the choice of punishing myself for making a mistake vs. adapting my environment to accommodate me, I'll always choose the latter.

(Plus, since you use `ls` so frequently, just make `l` an alias of it, especially if you have difficulty typing "ls"! Using a computer doesn't have to be some weird, punishing, bondage and discipline experience.)

Agree. It's why I alias . to pwd and .. to go up a directory.

Here are some of what I use:

    alias   -- -='cd -'
    alias     ..='cd ..'
    alias    ...='cd ../..'
    alias   ....='cd ../../..'
    alias  .....='cd ../../../..'
    alias ......='cd ../../../../..'
    alias l=ls
    alias la='ls -a'
    alias ll='ls -l'
    alias lla='ls -la'

I have had this in my .zshrc for years:

  # Quick ../../.. from https://github.com/blueyed/oh-my-zsh
  resolve-alias() {
    # Recursively resolve aliases and echo the command.
    typeset -a cmd
    while (( ${+aliases[$cmd[1]]} )) \
              && [[ ${aliases[$cmd[1]]} != $cmd ]]; do
    echo $cmd
  rationalise-dot() {
    # Auto-expand "..." to "../..", "...." to "../../.." etc.
    # It skips certain commands (git, tig, p4).
    # resolve-alias is defined in a separate function.

    local MATCH # keep the regex match from leaking to the environment.

    # Skip pasted text.
    if (( PENDING > 0 )); then
        zle self-insert

    if [[ $LBUFFER =~ '(^|/| ||'$'\n''|\||;|&)\.\.$' ]] \
           && ! [[ $(resolve-alias $LBUFFER) =~ '(git|tig|p4)' ]]; then
        zle self-insert
        zle self-insert
        zle self-insert
  zle -N rationalise-dot
  bindkey . rationalise-dot
  bindkey -M isearch . self-insert 2>/dev/null
For doing "cd ../.." I type "cd ...", each extra "." adds a "/.." to the argument.

It works for any command, cp/mv/whatever.

There may be nicer versions, certainly shorter versions are there if I search "rationalise-dot" in Google.

I personally have a single function that takes care of all of those dotted aliases:

    function up {
        local ups="."
        for((i=0;i<${1:-1};i++)); do
    	cd "$ups"

I appreciate the DRY-ness of it, but that requires you to type 'up ...' which is longer :(

A while ago when I was bored I was thinking of golfing those aliases to say (pseudocode):

    for i in 2..6:
      alias '.'*i=cd '../'*i
but I didn't know all the shell needed and just wound up leaving it as is.

Edit: turns out Zsh has a 'repeat' built-in:

    alias $(repeat 7 echo -n '.')="cd $(repeat 7 echo -n '../')"
Still, non-portable, less clear, not worth changing the aliases.

I’ve used these aliases since I first started using csh (below syntax for zsh):

  alias   .=cd
  alias   ,=pushd
  alias   ,,=popd
  alias   ,.='dirs -v'
No need to alias .. as in zsh you can use a dir name as a command to cd to it. Setting cdpath can further cut down on typing. For example

  cdpath=(. .. ~/go/src ~/src ~)

Why stop there? `shopt -s autocd`

those are great, definitely adding those aliases.

And "alias ...='cd ../../'" etc. Gotta love this feature.

It's a joke. I don't think anyone is mistyping it, as it's two characters on alternate hands on the home row.

I've mistyped it many times, precisely because it's alternate hands. Sometimes the left hand descends first.

Perhaps handedness is a contributing factor. I imagine even amongst practiced typists, the non-dominant hand tends towards more technical/physical errors than the dominant hand. Errors might include descending early, late, drifting from the center of keys, a tendency to follow the sequence of the fingers, etc....

I come to this idea because I am left-handed and if I have made this mistake, it has happened infrequently enough that I can recall neither a particular event nor the fact of such events having occurred. I would be curious about the handedness of people who make this mistake frequently (enough) and those who believe they do not.

It's one of the most famous mistyped commands


Not to be confounded with the other project of the same name (and with the same purpose) https://github.com/mtoyoda/sl

It's mentioned right in the very first paragraph of the article.

a beautiful web page, and its only CSS is this:

    body {
        max-width: 50em;
        margin: auto;
        padding: 1em;
        line-height: 1.5em;

    pre {
        overflow-x: auto;

Yeah, but that's some horrible use of the fieldset element ;)


Maybe i'm just weird but I can't recall ever making this typo, I find myself making letter-swap typos of words/commands with letters on the same hand often enough but that's not quite so easy with ls.

Maybe it’s your keyboard layout? I used to make this typo (ls -> sl) on QWERTY, but I later switched to Dvorak where both L and S are typed with the right pinky. I think it slowed me down enough on that keypair that it never happens anymore.

I was going to post this same comment. I letter-swap typos on many commands, but I've never in 20+ years made the typo of "sl" when I type "ls".

This code is incorrect: it has a a race condition that can cause it to use the wrong maximum width in its listing.

I'm not seeing it. Can you elaborate?

It invokes "ls" twice. There's no guarantee the maximum width obtained from the first invocation is still correct for formatting the result of the second.

I don't want to sound high and mighty or anything, but I've never mistyped 'ls'. I occasionally mistype other short binaries/commands, but typically anything more than ~4 characters has me hitting tab, and that usually completes uniquely and (obviously) correctly.

Then you're typing slower than you could.

By all means, type however you want to type, but if you never ever make a mistake, then you could push yourself harder.

Dunno about that. I type pretty fast (don't have exact numbers to back that up, just other people's comments) But regardless of that, typing two characters that are on opposite sides of the keyboard and each use a separate hand is, for me, pretty much error free. I make mistakes when letters are closer and using the same hand.

I don't think this is really accurate.

In my experience, the primary factor limiting my typing speed is the rate of errors. It's generally around 1-2%, but the time noticing and fixing those errors takes a disproportionate amount of time.

In other words, to type fast, learn to type accurately and gradually speed up while maintaining your accuracy.

I've never typed "sl" either. I have accidentally typed "l" and hit enter only to be surprised that it's aliased to "ls -CF".

For some reason I don't get ls wrong (right handed so maybe I reliably hit the l first) but I've had the following in my .alias for years

    # some common typos
    alias grpe grep
    alias gpre grep
    alias mroe more
    alias mreo more
    alias rmeo more

This didn't work on Mac OS due to "wc -L" so I whipped up a python version.


Long ago there was a ms dos. program called “rude dos” that if installed would replace the all commands with versions that randomly and rarely would refuse to work with various rude messages. I always ran it before letting my little brother use my computer :).

> Consider this code GPLv3 licensed.

is this actually valid? Does it mean the code _is_ GPLv3 licensed or not?

I think that is sufficient to make it GPLv3 licensed, but it places a bit of a burden on anyone who wants to redistribute it:

> 4. Conveying Verbatim Copies.

> You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.

If you want to redistribute it you have to go to your own efforts to give everyone you distribute it to a copy of the GPLv3 text.

Create a closed source product based on the code and find out!

Seems rather clear. The code itself also has a line indicating that license.

It is GPLv3 licensed, according to the second line.

The `wc -L` call fails on my Mac, but if I substitute gwc (as I have GNU coreutils available with a "g" prefix), it works.

This didn't work on Mac OS due to "wc -L" so I whipped up a python version.

not quite there but

alias sl='/bin/ls -l | tac | rev | column -t'

I was thinking this could be a simple alias with an AWK script.

In similar vein: express your inner rage while terminating offending processes.


Killing one memory hogging processor with another!

I always alias "ls" to "l"

Hi, author here. Feel free to ask questions!

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact