Use the clipboard from the command line

Dear new developer,

I’ve already written about the power of copy/paste to save effort. And had a guest blogger write about how you should be focus on inspiration rather than imitation.

This letter is going to be extremely tactical and reveal to you two commands that I didn’t know until a year or so ago.

But they changed my life. Well, they at least made my work copy/paste routine better. And reduced my mouse usage.

I spend a lot of time in a terminal, on the command line, but often want to copy between a terminal and a browser.

I might want to do this to paste an error message into a search engine. Or copy and paste a config file into a stack overflow question. Or even just type up something in a text file and copy and paste it into slack so that I can write something thoughtful without dealing with slack’s horrendous editing interface.

To do so, you can use these commands:

On macos, pbcopy. On Windows, clip.

Before I discovered these commands, I used to select text with my mouse and copy it, then paste it. It worked, but was inefficient.

Now, if I’m writing that aforementioned thoughtful response to a slack message, I might do the following:

vi a
# write thoughtful response
cat a | pbcopy
# cmd tab
# paste to slack
rm a

I use the temporary filename a because as soon as I finish writing it, I’ll be copying it to slack, which is where the thought will live permanently. But I still get to use my text editor.

Again, you can use this for any kind of text that you want to copy from the command line into the system clipboard. Error logs, sample commands, text files, configuration, anything. Copy it all!

Hope this helps,

Dan

Use your shell’s history

Dear new developer,

The command line is a powerful tool, and writing shell scripts lets you write a series of commands once and replay them any time you like.

But sometimes you will write a series of commands without putting them into a script. This may be because you are exploring a problem or because you haven’t bothered to put together a script. No sense in making something repeatable if you aren’t sure exactly how you are going to repeat it.

But you may want to look back over past commands you have run, whether to run them again, modify them or even just remind yourself what you’ve done. For this, the shell history is very handy. Another time I often look at the shell history is when I am signing into a machine that I don’t visit very often. Perhaps there’s a command to look at some log files that I know, distantly, in the back of my mind, that I ran four weeks ago. I could have documented it, but maybe I didn’t. If I look in my command line history, I can see it.

All of the examples below are for the bash shell. Why? This is a very common shell, more modern shells like zsh are roughly compatible, and most importantly, this is the shell I know.

To use the shell history, first you have to know it exists and then you have to see it. You can also view the history by typing history in your terminal or at the shell prompt. Here’s an example from one of my shells:

  520  vi text.adoc
  521  git status
  522  git add text.adoc
  523  git commit -m "Initial pass at examples and documentation."
  524  vi text.adoc
  525  git add text.adoc
  526  git commit -m "Added one more example." text.adoc
  527  git push origin add-example-docs
  528  history

Each line is one command and is numbered. From here, I can repeat a command by number. So if I type !524 the command vi text.adoc will be run. I can also search for a certain string by using grep:

history | grep 'ssh' # will show all my ssh commands

The above commands are all pretty simple, but you can also link commands together. I often will do something like this:

cd directory && mvn jar && cp file.jar ~/place/jar/goes && cd otherdirectory

Once I get this command right, I can run it over and over again by referencing its line number. The && means that each command has to succeed before subsequent commands are run. So if the mvn command fails, the cp will not run.

This is fine for running tasks that are not going to change, but what about if I want to edit my previous commands. You can navigate the history by using the arrow keys (there are other ways as well, but arrow keys are the default and most accessible). Each up arrow takes you one step further back in your history, and each down arrow takes you one step forward. At any point you can edit the command you are currently on and hit the enter key and run it.

The bang shortcuts

If you know you want to edit whatever command you ran previously, you can use some bang operator shortcuts (so called because “bang” refers to a !). Let’s say I want to get the latest main branch from my git repo.

Suppose I run the command:

gti fetch origin main

I see an error message because I misspelled git. Whoops. I can type:

git !*

!* expands to everything except the first argument in the previous line, so this is the command that is run:

git fetch origin main

Now I want to check out the main branch

git checkout !$

!$ refers to the last argument of the command, so main in this case. The command which is run is then:

git checkout main

Knowing these shortcuts will help you avoid tediously hitting the arrow keys, editing the previous command and re-running it. There’s one more bang shortcut which is very useful. Suppose I want to install something on a linux box:

apt-get install pkgname

Whoops again! I’ll get an error message because I’m not root. Easily fixed by typing:

sudo !!

!! expands to the entire previous command, so what is actually run is:

sudo apt-get install pkgname

I use this very often when working with linux on the command line.

Controlling what is saved

You can control how much history is kept. Sometimes on my development machine I keep an infinite amount of it. I’ve also been on production instances where there was no history kept, I believe as a security measure. Remember, any command you run, including opening up a database connection using a command line client, will be kept in the history buffer. If you put a password on the command line, it will be recorded in this history.

To avoid that, don’t put the password on the command line. Another trick is to set the HISTCONTROL variable. When this is set to ignoreboth any command you type with a space in front won’t be stored in the history.

export HISTCONTROL=ignoreboth # previously set
echo "hello" # included in history
 echo "goodbye" # not included

You can also control explicitly how many commands to store in your history with the HISTSIZE setting:

export HISTSIZE=2000 # will save 2000 commands

Finally, be aware that all the bash shells opened share the same history file. Unless you take special care (as outlined here) the last one closed will win.

Being able to quickly re-run commands you’ve built previously, whether unchanged or not, can be helpful when you are navigating around the command line in pursuit of your software goals. Knowing a few history commands lets you do so.

Sincerely,

Dan

Learn the command line

Dear new developer,

I remember the first time I saw a senior engineer struggle with the command line. He was a new hire and was getting up to speed on a new project. If memory serves, he was trying to get his IDE set up for a java project.

I noticed him with the command line open, trying to remember how to move around directories, and wondered why he was having such trouble. (Probably I felt the same way some developers feel about me when I struggle with CSS or cutting up a PDF or reading C–“how could you be a developer without understanding this?”.) I never talked to him about this, but it cemented in my mind why a new developer should learn the command line inside and out.

It’s a baseline.

The command line interface (CLI) will always be available. Wherever you are (unless you are on an old mac, pre MacOS X, in which case, why?).

Unlike some of the skills I mention above, knowing how to navigate the command line will make your life easier as a developer no matter where you work or in what platform or capacity. It’s a general purpose skill, like understanding how to use version control or learning a text editor.

Understanding the command line and being able to use it has the following benefits. Let’s take a simple task–I need to move a file into a directory, change the permissions on that file, then look through the file for a certain phrase (say, “rosebud”). With a CLI, I can:

  • accomplish the task in less time. I can move files, change file permissions, and look through files far quicker with command line tools than I can with any GUI (graphical user interface) tools. (There are any number of other tasks I can accomplish more quickly, as well.) The kicker is, of course, the first few times I do this, I will be slower on the command line than I would have been using a GUI. This is because you have to learn the CLI and the cues to help you do so are minimal. You of course also have to learn a GUI (anyone who’s ever shown someone a GUI for the first time know that) but there are more cues on what is the right behavior in a graphical context. But once I have it down, the typing the commands will be much quicker than moving the mouse.
  • make tasks repeatable. If I’m trying to move a file, change its permissions, and see if it contains “rosebud”, I can do this once easily in the GUI, using the mouse and menu commands. But doing this task regularly, whether once a day, once a month or once every time a piece of software is released is quickly going to get tedious. I can, on the other hand, do it once in the CLI, and then take the CLI commands and put them into a script (a text file that becomes executable). Then that same set of commands will be run every time I run the script. This may not matter if task is simple (as is my example of only three commands is), but if it is complex, getting it right once and having it run perfectly every time thereafter will be a huge time and energy saver. If executing the task is common, then you will save time because you will run it often. If executing the task is rare, you will save time with a script because you won’t have to remember how to run the command.
  • share tasks with other people. Yes, you could record a video of yourself clicking through a GUI to move the file, change its permissions and look for “rosebud”. Or you could document the actions in detail and send the doc over. Or if you are colocated, you could show them. But it’s much easier to just send someone else an executable script or set of commands that they can examine and run. As long as they have access to the same command line programs, you’re going to get the same results. (Beware different versions of the same command line program, especially if you are using esoteric commands or working on different operating systems.)

Hopefully I’ve convinced you to learn the command line. Now, what are good ways to learn it?

I think that one path is to just jump in. Find the “terminal” program if you use a mac, or the “cmd” program if you use windows. Open it up. Then google for “command line tutorial <platform>” and work through one of those. I always work best when I have a real task, so think of something you do often (for example, opening up a number of files for a project, moving files to a backup directory) and do it once in the GUI. Then do it once in the command line. Then make a script for it. See how that feels. If you are scared of messing up your computer, install a VM or boot up a cloud server (most cloud providers will give you a small server for free for a while). You can’t screw up a VM that you just started, and if you do, just destroy it and start a new one.

Another option is to think about mapping between the GUI/IDE and the command line. Every time you do a task in the GUI or IDE, drop down into the command line and try to replicate that. From something as simple as moving a file to something as complex as a full fledged deployment or compilation of a large project.

As you get more advanced, you have the option of sharing your keybindings between your editor and your shell. Just google “keybindings <editor> <shell>”. I use vi keybindings for my bash shell and it lets me move around the command line with ease and speed. And every time I learn a new way to move around the editor, my CLI usage gets better.

The command line is underneath almost every computer. Learning it will save you time and let you leverage knowledge. Well worth the effort.

Sincerely,

Dan

PS I would be remiss if I didn’t link to this essay about the command line.