3 Linux Command Line Programming Boosters

The following is a description of three linux command line features I use on a regular basis that provide a strong boost to my productivity.

Pipe to clipboard

From the command line it is trivial to redirect output to a file via the > operator. However there is no native support for the same redirection to the global clipboard. I commonly find myself in the situation where I would like the result of a command to be stored in the clipboard so that I can easily paste it into a GUI application or just to save it for use in the next command.

The way to do this is through the xclip application. To get it I would first recommend that you use the package management system of your distro; for me this is:

radman@computer:$ sudo aptitude install xclip

Failing that you can get it directly from the sourceforge page here

Now you can redirect something to the clipboard using:

radman@computer:$ <command with output> | xclip -selection c

And you will be able to paste it anywhere you like.

Making it a little more convenient

Now direct usage of xclip is a bit wordy and not particularly expressive and has some issues with newlines when pasting blocks. To overcome these limitations I have written a script to smooth out the bumps.

Name this script clipboard, make it executable and copy it to the /usr/bin folder (so it's in the path).


#!/usr/bin/python

import fileinput
import sys
import subprocess

xclipProcess = subprocess.Popen('xclip -selection c'.split(), stdin=subprocess.PIPE)

printLine = ""
for line in fileinput.input():
  if printLine:
    xclipProcess.stdin.write(printLine)

  printLine = line

temp =  printLine.rstrip()
if printLine.endswith("\n"):
  xclipProcess.stdin.write(printLine.rstrip())
else:
  xclipProcess.stdin.write(printLine)

With that done you should now be able to execute the ever so convenient:

radman@computer:$ <command with output> | clipboard

Programming Examples

I tend to work from the command line quite heavily when programming and I'll show a couple things that I use pipe to clipboard for.

Get the current working directory

So you're in some deeply nested folder on the command line and need to grab the path for a debugger, IDE or other task. Simply use the command:

radman@computer:$ pwd | clipboard

My previous solution for this was to use the mouse to highlight and copy it from the shell console, ick.

Get remote subversion path from local checkout

I often need to make a another checkout of the same repository I already have locally when working with Subversion. To extract the remote path for the checkout just cd to the root of the local checkout and execute:

radman@computer:$ svn info | grep URL | grep -Eo 'svn.+' | clipboard
radman@computer:$ svn co <paste> ~/check/out/to
Grab the contents of a file

I sometimes need to grab the contents of a file for pasting purposes, doing this is trivial:

radman@computer:$ cat <file> | clipboard

Find with exec

Find is an extremely useful command to know and if you can get into the habit of using it's exec features complex repetitive tasks become a breeze. Find is a part of the findutils GNU toolset and should come by default on all linux flavours. Find recursively searches for files in a directory hierarchy and provides the results to you.

Noob's guide to find

Find, like most gnu command line tools, find has a daunting amount options and switches to frighten newcomers. However the most common use case (at least in my case) is pretty straightforward to learn.

radman@computer:$ find <where to search> -name '<search pattern>'

Where search pattern can be any of the normal globbing patterns e.g.*.ext, startofname* etc. So if you wanted to find all cpp files starting in the current folder the command would be:

radman@computer:$ find . -name '*.cpp'

Pretty easy huh?

Using the exec feature

The exec feature in find allows you to execute some arbitrary command for each positive result given by find. What this boils down to is that you can automatically have something done to every file found by find.

The syntax for using exec can seem scary but it is actually pretty simple. All you need to do is add
-exec <command> {} \;
to the end of your find command.
So from the previous example:

radman@computer:$ find <where to search> -name '<search pattern>' -exec <command> {} \;
Examples

First a simple one; You can get extended information about the cpp files in the current folder like this:

radman@computer:$ find . -name '*.cpp' -exec ls -hal {} \;

This does a ls -hal on each file.

Now, a favourite of mine; Get names of files that include a certain header, or type of header:

radman@computer:$ find . -name '*.cpp' -exec grep -El 'include.+boost' {} \;

So this will tell you which files include a boost header, it executes grep -El 'include.+boost' for every file found by find.

As you can see there are some really great and convenient things you can do once you master find with exec and the examples given just start to scratch the surface.

Improving reverse-i-search

You may well know of a feature of the bash shell called reverse-i-search where you can do a search through previously executed commands and run them. This is useful when you use a particular command (or similar command) often. However I always found that I couldn't find what I wanted even though I thought it should have been there, this was frustrating and caused me not to use it.

As it turns out reverse-i-search only records history for the current shell so as soon as you close it you lose the history. If you are using multiple tabs then obviously commands in one are inaccessible in another. These were the limitations that prevented from using the feature productively so I tried to find a workaround. As it turns out you can 'turn on' aggressive recording for this so that all commands in any shell are added to the history, which is accessed by all shells when using reverse-i-search. It also keeps the history separate from any one shell so that you can successfully reverse-i-search commands you made a week and more ago!

To turn this on all you need to do is add the following to the bottom of your .bashrc, usually located at ~/.bashrc:


# shared and aggressive history recording between tabs
export HISTCONTROL=ignoredups:erasedups # no duplicate entries
export HISTSIZE=100000 # big big history
export HISTFILESIZE=100000 # big big history
shopt -s histappend # append to history, don't overwrite it

# Save and reload the history after each command finishes
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"

Now unfortunately there is a small downside to activating this... Because the history is not stored per shell you constantly lose the immediate history of individual shells, which breaks pressing up to get your last command. So if you work in a shell and then come back to it after working elsewhere the execution of your first command will erase the history of that shell. For me this was not a big issue as a quick reverse-i-search can find any command that you want, I actually found this to be an upside as it forced me to use the search feature more often!

This is definitely a personal preference change so give it a go and see if you like it. To disable it again all you have to do is remove the line from the .bashrc and everything will go back to normal again. I highly recommend it, it actually made the feature usable for me.

Summary

I hope you find the tips above useful (I know I love them) and I would make one further recommendation for using the linux command line effectively. Learn to use grep, |'s and regex, they are the enabler for combining different features of the command line. Once you have those down it is reasonably easy to accomplish most tasks with little effort.

2 Responses to “3 Linux Command Line Programming Boosters”


  1. for mac osx pbcopy (instead of xclip)

    cyphis
    June 5th, 2013
  2. Very nifty. This is especially nice for copying very large outputs (like ps -ef) to the clipboard. Much better than click-dragging!

    After reading this I have also made a script called ‘pasta’:
    #!/bin/bash
    xclip -se c -o

    This is for the odd occasion for when you want use multi-line clipboard content in bash; ctrl+V pasting results in every pasted line executing as a command.

    USAGE
    ===Print clipboard:
    pasta

    ===Assign clipboard to variable:
    BAH=$(pasta)

    SplicerDan
    February 3rd, 2014

Leave a Comment