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
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
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
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
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
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
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
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
All right, let's see if you guys have a clue about this:
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 argumentsrepo
andtag
, this will translate to: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: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
prints2+2+2
into the output, andcommand-2
evaluates mathematical expressions from keyboard and prints the output, thencommand-1 | command-2
will basically make the2+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
. Thehead
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, thehead
command will print the firstn
lines and then ignore the rest. We specifyn
with the-n2
flag, and its value is set to2
.So the
head
command will print the first two lines from the table: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 lastn
lines from the input, and print those lastn
lines. In this case, we invoke it withtail -n1
, thereby settingn
to1
. The last one line will be printed.Or at least,
tail
will try to print it. But its own printed output has been further piped into thecut
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: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:
Which is the final form of the command, and it is executed. So the command does this:
Wow.... That's actually quite useful
Thank you. I use this one a lot, though I typically write it out in just one line.