My command line and shell cheat sheet

I've added a command line and shell cheat sheet to my public references.

Pretty much all of the uses of these tools hit a middle ground of not using them enough to have really memorized them, but enough to have looked up the options I want to use quite a few times now. There's also no "discoverability" with command line tools besides looking at documentation, but that usually shows all the options which you have to search through every time.

Anyways, I figured I would dedicate the rest of this post to more detailed descriptions of the tools than in the cheat sheet currently for anyone who might be unfamiliar with any of them.

tar

Every command line cheat sheet should have an entry about tar. You don't want to be stuck without it.

When you want to download a file from the internet, it will occasionally be a .tar.gz or .tgz file which is a compressed file that needs to be decompressed. You can use the command tar -xf $FILE to decompress it.

Finding files

There's two main commands for finding things in the file system: locate and find. You'll probably want to use locate more often since it's faster, but it uses a database to find things which can get out of sync with what's actually in the file system. If you cloned a git repo recently for example, you might want to use find. You can use updatedb to update it, but it can take a while if it's very out of date and usually requires root/sudo access to update. find also has more options including the ability to run shell commands on the results.

locate

For a while I used find more often than locate because the regular locate command searches the entire file system, rather than using the current directory as a base, which usually returned a lot more results than I wanted. However, in doing some research for this post I found you can use parameter subsitution to search from the current directory with locate "$PWD*/<FILE GLOB>".

find

The interface for find is a bit strange since the options go after the path argument and it uses single dashes - for full word options rather than single character options with a single dash and two dashes for full word options. It also might seem kind of strange that it doesn't just have the name be another positional parameter, but you can use find without a file name such as find . -empty -delete which deletes empty files.

There's a bunch of command line options that you might find useful. You can also learn more about it in the GNU findutils manual.

Shell/Bash

Mostly this section is just a collection of random things about the shell languages' syntax and operation. Being able to automate things within the operating system is an extremely useful ability, however I find most shell languages have a lot quirks and other strangeness that make them a bit unpleasant to script anything more complex than a list of simple "single line" commands. My uncomfortableness is probably somewhat because of my relative unfamiliarity with things like streams, processes, scope with the different processes, and the Linux operating system itself and I know that a lot of the design is to make things like parameter substitution and executing strings as commands easier. However treating values like numbers, dates, or anything other than strings, and getting the right combination of brackets, parens, and dollar signs in your scripts is always confusing.

Having a cheat sheet is very helpful for this kind of thing, but I'd really just like to use a more familiar language for shell scripting. Bash and similar shells are quite a bit different than a lot of languages nowadays, even if bash existed before a lot of them. I'm more familiar with those languages though and even if some of those features make some shell tasks a bit easier and I've only got a limited strangeness budget. There are libraries for existing languages that help for creating shell scripts, and there are other shell languages out there (I've listed a few below), but I just haven't gotten around to investigating either of those possibilities yet.

A note on referring to "shell" and "bash"

(I'd normally probably add this bit as a footnote, but I haven't set those up with my blog yet.)

For all the pedants out there like myself, referring to the correct shell language/implementation can be a bit tricky. A lot of people refer to shell scripts as "bash scripts" however if you're using #!/bin/sh in a shell script, it's probably not technically bash since, as this StackOverflow answer points out /bin/sh is usually a link to a POSIX compliant shell and bash is not (completely) POSIX compliant. In Debian and Ubuntu /bin/sh usually points to dash. That's why I'll usually just try to refer to them as "shell" scripts.

diff

diff's a tool to find differences between two files or directories full of files. If you use git you've probably used git diff for comparing different versions of the same file. diff is useful if the files aren't in git or just aren't different different version of the same file.

I actually use vimdiff more often to compare files, but if you want to compare directories, or just want a quick diff then diff's alright.

rsync

rsync copies files from one location to another location, whether that's to another directory on the same computer, to a directory on a separate computer that it has access to. It's a little more complicated to use than cp or scp so you using it for simple copying might not make sense, but it's useful for moving large amounts of data since it's faster, or as part of an automated process.

lsblk

As mentioned in the cheat sheet it lists devices. I've used it repeatedly to identify external hard drives, especially on computers without a GUI like my home server.

udisk

Automatically mounts devices to /media. If you don't have a particular place you want to mount an external storage device to it's a little more convenient than mount and umount since you don't have to specify where to mount it to and you know all external storage will be mounted in the same place.