DEV Community

Discussion on: Share a code snippet in any programming language and describe what's going on

Collapse
 
rajarshi profile image
Rajarshi Bandopadhyay • Edited

All right, let's see if you guys have a clue about this:

docker commit `docker ps -a |\
    head -n2 |\
    tail -n1 |\
    cut -d" " -f1` $1:$2
Enter fullscreen mode Exit fullscreen mode

This is a single line of shellscript code written over three lines for readability. Notice that it employs backticks inside the code.

A lot is happening here, obviously. FIrst of all, the $1 and $2 will be replaced by the first and second command line argument respectively. So if you are invoking this script with the command line arguments repo and tag, this will translate to:

docker commit `docker ps -a |\
    head -n2 |\
    tail -n1 |\
    cut -d" " -f1` repo:tag
Enter fullscreen mode Exit fullscreen mode

Next, note the backticks inside the command. The portion between the backticks - will first be evaluated. The result of this evaluation will then replace the entire thing inside the backticks.

Now, what does the portion inside the backtick do? Well, it has four parts:

Part 1 is docker ps -a, which yields a list of Docker images and their details:

CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS                     PORTS     NAMES
20d03205fe06   ubuntu:20.04   "bash"                   3 seconds ago   Exited (0) 2 seconds ago             bold_feynman
dcf460b2c4ff   07cd54330caf   "/bin/sh -c 'tar xzf…"   4 minutes ago   Up 4 minutes                         blissful_liskov
Enter fullscreen mode Exit fullscreen mode

This output is then piped into part 2. Piping is a special construct in Shellscript, which takes the string output of one command and puts it into the string input of the next command. So if command-1 prints 2+2+2 into the output, and command-2 evaluates mathematical expressions from keyboard and prints the output, then command-1 | command-2 will basically make the 2+2+2 from the first command become the input of the second, and we will only see the final output - 6.

The output of the first command is being piped into the second command, which is head -n2. The head command snipes out the first n lines from a file (or text input), and prints it. When fed the lines of details of different classes at the input, the head command will print the first n lines and then ignore the rest. We specify n with the -n2 flag, and its value is set to 2.

So the head command will print the first two lines from the table:

CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS                     PORTS     NAMES
20d03205fe06   ubuntu:20.04   "bash"                   3 seconds ago   Exited (0) 2 seconds ago             bold_feynman
Enter fullscreen mode Exit fullscreen mode

Notice that this includes the heading row and the details of the latest image - in this case, one which was created just three seconds before this command was run (I admit to having created it just to demonstrate this snippet).

The next command in the pipe is tail, and this command will ignore all but the last n lines from the input, and print those last n lines. In this case, we invoke it with tail -n1, thereby setting n to 1. The last one line will be printed.

20d03205fe06   ubuntu:20.04   "bash"                   3 seconds ago   Exited (0) 2 seconds ago             bold_feynman
Enter fullscreen mode Exit fullscreen mode

Or at least, tail will try to print it. But its own printed output has been further piped into the cut command. This command does something quite whacky: it takes two arguments, known as the delimiter and the selected columns. The delimiter has to be a char and the selected columns is a comma-separated sequence of numbers. In case a single number is provided, that single number is interpreted as a single-length sequence of numbers.

What cut does is that it splits each line of its input into parts, separated by the delimiter. It then takes the specific values which correspond to the selected columns, and then prints only those values which have been selected.

For instance, in this case, it will split the input string (which is a single line) by the " " space character, and then take out the first member of the resulting array of substrings. Of course, this effectively means that it will only pick the first word of the line. And in this case, that word is the container ID of the most recently run container:

20d03205fe06
Enter fullscreen mode Exit fullscreen mode

This ID is the final output of the entire portion inside the backticks, and given the way Shellscript works, the entire portion inside backticks will simply be replaced by this one container ID number:

docker commit 20d03205fe06 repo:tag
Enter fullscreen mode Exit fullscreen mode

Which is the final form of the command, and it is executed. So the command does this:

It commits the most recently run container as an image with the name and tag provided as command line arguments to the script

Collapse
 
pandademic profile image
Pandademic

Wow.... That's actually quite useful

Collapse
 
rajarshi profile image
Rajarshi Bandopadhyay

Thank you. I use this one a lot, though I typically write it out in just one line.