Tips & Tricks to master BASH

Tips & Tricks to master BASH

Bash is a highly important tool, especially when dealing with Linux-based servers. As much as we use the terminal, be it for a remote shell or configuring web access, it is important that we are efficient with it. Here are some tips I learn to make myself more efficient in the terminal.

Setting a meta key (alt)

I like to set alt as a meta key. Without this setting enabled you have to use the esc key instead. I recommend enabling the alt key. In GNOME terminal Edit > Keyboard Shortcuts > uncheck “Enable menu access keys.”

The magic word that lets you reduce the number of key presses on the one hand and avoid the potentially fatal consequences of typos on the other is completion. There probably isn’t a command-line user alive today who doesn’t appreciate the Tab key, which completes commands at the start of the line as well as directory names and file names.

Starting with the Basics

The magic word that lets you reduce the number of key presses on the one hand and avoid the potentially fatal consequences of typos on the other is completion. There probably isn’t a command-line user alive today who doesn’t appreciate the Tab key, which completes commands at the start of the line as well as directory names and file names. However, quite a few people are probably blissfully unaware of the double-Tab shortcut – I mean Linux users who stand alone like a lighthouse in an ocean of Windows users. No kindred spirits will look over their shoulders and say: “There’s no need to type ls cd ls …; just type cd Tab-Tab instead, and the shell will show you a list!”

Completion isn’t a core feature of Bash, it’s part of the Readline library. The Readline complete() function triggers automatic completion of a text and is normally linked to the Tab key. Many programs use the Readline library, which explains why the completion mechanism is also available in these tools.

At the command line, the text in front of the cursor is decisive. If it starts with a dollar sign ($), Readline will search the list of variables; a tilde (~) triggers a search in the list of users defined in /etc/passwd, and a commercial at (@) searches in the list of hosts. Text without one of these special characters at the start of the line is interpreted by the completion mechanism as the start of the command – including aliases and shell functions. If nothing else is appropriate, Bash will try file name completion; that is, complete() will try to add the name of a file or directory in the current directory to the text.

The magic word that lets you reduce the number of key presses on the one hand and avoid the potentially fatal consequences of typos on the other is completion. There probably isn’t a command-line user alive today who doesn’t appreciate the Tab key, which completes commands at the start of the line as well as directory names and file names. However, quite a few people are probably blissfully unaware of the double-Tab shortcut – I mean Linux users who stand alone like a lighthouse in an ocean of Windows users. No kindred spirits will look over their shoulders and say: “There’s no need to type ls cd ls …; just type cd Tab-Tab instead, and the shell will show you a list!”

Completion isn’t a core feature of Bash, it’s part of the Readline library. The Readline complete() function triggers automatic completion of a text and is normally linked to the Tab key. Many programs use the Readline library, which explains why the completion mechanism is also available in these tools.

At the command line, the text in front of the cursor is decisive. If it starts with a dollar sign ($), Readline will search the list of variables; a tilde (~) triggers a search in the list of users defined in /etc/passwd, and a commercial at (@) searches in the list of hosts. Text without one of these special characters at the start of the line is interpreted by the completion mechanism as the start of the command – including aliases and shell functions. If nothing else is appropriate, Bash will try file name completion; that is, complete() will try to add the name of a file or directory in the current directory to the text.

To support all this complet

Repeat Commands

I spend a lot of my time in terminal repeating commands that I have previously run. And yes, the first way I learn to repeat commands was to use the up and down arrows to navigate the history of commands. This is terribly inefficient. It requires repositioning your hands and often times removing your eyes from the computer screen. Also, your history (depending on your HISTSIZE) can be very long. Instead of searching line-by-line I use search history (ctrl-r and ctrl-s).

In your terminal window, before you type any text press ctrl-r and you should see your prompt change to (reverse-i-search):. Now begin typing any part of any previous command you have executed and you will see the most recent command which matches your search. If this is not the one you want, press ctrl-r again to search incrementally. For example, if you are searching for kubectl delete pods -l=app=nginx you would type kubectl or kubectl del. You should land on that command. If, while incrementally searching backward, you pass the one you’re looking for, press ctrl-s to go the other direction and you will see your prompt change to (i-search):. Once you find the command you want press enter to execute it or move the cursor left/right to modify the command first.

Sometimes you know that the command that you want to repeat is only two or three places back in history. In these cases it is sometimes easier to move up to that command directly. But you still should not use the arrow keys. Bash has keyboard shortcuts for this too! Here is where we use ctrl-p for “previous” or ctrl-n for “next.” Pressing ctrl-p moves to the previous command in history (replacing the up arrow), and ctrl-n moves to the next command (replacing the down arrow).

In mose cases your history will probably be set to record duplicates. This gets pretty annoying for me so I use the following setting to make sure my history doesn’t get flooded with duplicate entries. Add this to your ~/.bashrc or ~/.bashprofile and your history will only keep the newest versions of commands. If you typed git status seven times, it will only record the latest one and delete the previous entries.

Movement

Now that we know we don’t need the up and down arrow keys, what about the left and right? Unfortunately, these keys are still needed for single character movements, but I find myself using them less often. Here are some key combinations to move your cursor a little more efficiently.

  1. ctrl-a – move the cursor to the beginning of the current line
  2. ctrl-e – move the cursor to the end of the current line
  3. alt-b – move the cursor backwards one word
  4. alt-f – move the cursor forward one word
  5. ctrl-k – delete from cursor to the end of the line
  6. ctrl-u – delete from cursor to the beginning of the line
  7. alt-d – delete the word in front of the cursor
  8. ctrl-w – delete the word behind of the cursor

The last four aren’t necessarily movements, but I use them in conjunction with the above most of the time.

Copy / Paste

If you are familiar with Windows, then you would know Ctrl-C and Ctrl-V, but in a Bash terminal, it would be hard to find one that responds to the above standard commands. You can use | pbcopy. Append it to the back of the command.

Changing Directories

cd is one of my most used commands according to my bash history. One thing I find myself doing a lot is changing between two directories or briefly changing from directory a to directory b and then back to a. Depending on the reason I’m changing directories I will use either cd - or a combination of pushd and popd. If you type cd - and press enter, you will change to your previous working directory.

On the other hand, sometimes I know that I want to go to some directory in a different place, but I might cd a few times to get there, but I want to mark my place so that I can get back quicker. In this case, you would use pushd like this.

cd ~/go/
pushd ~/tmp/ # mark your current directory and cd to ~/tmp/
cd ssl
cd certificates
# cd - <- this would take you back to ~/tmp/ssl because it is the previous working directory
popd # <- this takes you back to ~/go/

You can pushd multiple times to build a stack. I don’t find myself doing this much, but it’s there if you need it.

Background Processes

If you close a terminal, whatever active tasks stops with it.

If you need to run a command indefinitely you can send it to the background by first running it and then pressing ctrl-z. This will suspend or pause the process. After it has been suspended, type bg and press enter. This will move it to a running state, but it will no longer have control of your terminal window. However, if you close the terminal that job will terminate. To avoid this, you disown the process by typing disown and pressing enter. At this point the process is no longer a child of your current terminal process. I often use this to run kubectl proxy or python -m SimpleHTTPServer.

  1. ctrl-z – move the current process to the background in a suspended state.
  2. jobs -l – list the current background processes for the current tty session.
  3. bg – tell the most recent background process to continue running in the background
  4. fg – bring the most recent background process back to the foreground
  5. disown -h – disown the most recent background job. This will remove it from your current tty session. It will not be able to be brought back to the foreground. You will have to control it either with kill or something else.

bg, fg, and disown can be used with the job number found in jobs -l. If you run jobs -l you will see the job number at the beginning of the line. If you want to bring the 2nd job to the foreground you run fg %2. If you want to disown the fourth job then you run disown -h %4, and so on. The plus sign (or minus sign) at the bigging of the line has meaning as well. A plus sign indicates that the job is the most recently used, or the one that will be targeted if you type any of the commands without a job ID. The minus sign is the second most recently used.

I use ctrl-z a lot because I use a single terminal window for vim and as my command line interface. When I’m writing code in vim and I need to get back to my shell prompt I use ctrl-z to suspend vim. NOTE this will still print stdout and stderr to your command window. If you want to change that then you can redirect to files

I modified my PS1 to show my current background job count.

function jobs_count {
    cnt=$(jobs -l | wc -l)
    if [ $cnt -gt 0 ]; then
        echo -ne " \e[93m${cnt}\e[m"
    fi
}
# then you can add \`jobs_count\` to the end of your PS1 like this
export PS1="\[\e[32m\]\u\[\e[m\]@\[\e[32m\]\h\[\e[m\]:\[\e[34m\]\w\[\e[m\]\`git_branch\`\`jobs_count\`\n\$ "

Working With Files

Several times throughout the day I want to view the contents of a file. Before, I would cat the file or open it in vim. cat was annoying because it flooded my terminal history. This is when I learned to use less to open files with pagination. When you open a file with less the contents of the file become paginated and you start at page one. What’s great about lessis that many of my favorite key combinations work. You can use ctrl-u to page up, ctrl-d to page down, ctrl-p to scroll up one line, ctrl-n to scroll down one line, g goes to the top of the file, G goes to the bottom of the file, and / searches the file.

While less is great for opening files, I may not know where the file is in the first place. Say I have a file named “auth.py” but I don’t remember exactly where I put it. I could cd back and forth until I find it, or do what some people do and run start . and browse for it in a UI window (terrible workflow). Instead, I use either find, ag (silver searcher), or tree. find is great for searching by file name. You can run find . -type f -name auth.py to search the current directory for a file named “auth.py”. tree is great for listing a directory in a tree format (much like how you see it in a UI). ag is an applciation called “the silver searcher.” It is essentially a modernized version of grep and I find myself using it quite often. It’s better than grep in that it automatically ignores commonly ignored files such as the .git directory, virtualenv, and anything listed in your .gitignore. I like silver searcher because the command line arguments are very similar to grep so my flags are generally transferrable. Note It’s best to combine these commands with less because they will likely flood your terminal history.

Choose a Few to Start With

I did not use all of these when I first started using bash, nor did I memorize them all at once. I picked up one or two here and there over the years. It’s difficult to memorize key combinations, especially when there are so many of them. Pick one or two shortcuts and focus on using them. I find myself using these commands by muscle memory, not by memorizing each keyboard shortcut. In fact, once I started to write this I had to open up the terminal and work around to remember which shortcuts I use. I hope these help you work with bash and terminal more effectively. It is easy to learn one new trick and force yourself to use it for a few days until you get used to it. Once you are comfortable with that command, pick up another one.