6

I have a list of currently installed kernels, and I'm trying to grep out both the currently installed kernel and the previously installed kernel. For this example, linux-image-3.2.0-60-generic is the currently running kernel, and these are the installed kernels:

linux-image-3.2.0-49-generic
linux-image-3.2.0-51-generic
linux-image-3.2.0-52-generic
linux-image-3.2.0-53-generic
linux-image-3.2.0-54-generic
linux-image-3.2.0-55-generic
linux-image-3.2.0-56-generic
linux-image-3.2.0-57-generic
linux-image-3.2.0-58-generic
linux-image-3.2.0-59-generic
linux-image-3.2.0-60-generic
linux-image-3.2.0-61-generic
linux-image-3.2.0-63-generic
linux-image-3.2.0-64-generic

I can use grep -v $(uname -r) to remove the currently running kernel from this list. However, I can't seem to use grep -v -B 1 $(uname -r) to remove current and previous kernel from the list. Is there a way to combine the -B and -v? Or am I approaching this entirely from the wrong direction?

4
  • 1
    -B N means to print N lines before the lines that are printed. When used with -v, it means to print lines before the lines that DON'T match. Which basically means that it will N lines that match the regexp before each non-matching line.
    – Barmar
    Commented Jun 6, 2014 at 20:06
  • I think you should be able to do what you want with awk pretty easily. Save the previous line in a variable. When you read a line that doesn't match the current version, print the saved line, and put the current line in the variable. When you read a line that DOES match the current version, clear the variable and don't print anything. Finally, print the saved line in the END block.
    – Barmar
    Commented Jun 6, 2014 at 20:09
  • From where you get the list of kernels as output? Is it from any file?
    – Ramesh
    Commented Jun 6, 2014 at 20:30
  • No, it's from some crazy grepping: dpkg -l linux-image-[0-9]* | grep "ii " | grep -oE linux-image-[a-zA-Z0-9.\-]\{0,\}. This only works on Debian-based systems, of course.
    – zymhan
    Commented Jun 6, 2014 at 21:12

3 Answers 3

3

You can use 2 grep's to get what you want. The interior grep will generate the "list" of matches for the current kernel, uname -r and the previous reversion to it. The exterior grep will give you the list of kernels excluding these 2.

$ grep -v "$(grep -B 1 "$(uname -r)" list.txt)" list.txt

Example

To simulate what you have I've added the contents of these to the file list.txt.

$ cat list.txt 
linux-image-3.2.0-49-generic
linux-image-3.2.0-51-generic
linux-image-3.2.0-52-generic
linux-image-3.2.0-53-generic
linux-image-3.2.0-54-generic
linux-image-3.2.0-55-generic
linux-image-3.2.0-56-generic
linux-image-3.2.0-57-generic
linux-image-3.2.0-58-generic
linux-image-3.2.0-59-generic
linux-image-3.2.0-60-generic
linux-image-3.2.0-61-generic
linux-image-3.2.0-63-generic
linux-image-3.2.0-64-generic

Now let's pretend that the command uname -r returns this string:

$ uname -r
3.2.0-60-generic

So when I run this command I get a list of the kernels minus the uname -r and the version previous to it.

$ grep -v "$(grep -B 1 "3.2.0-60-generic" list.txt)" list.txt 
linux-image-3.2.0-49-generic
linux-image-3.2.0-51-generic
linux-image-3.2.0-52-generic
linux-image-3.2.0-53-generic
linux-image-3.2.0-54-generic
linux-image-3.2.0-55-generic
linux-image-3.2.0-56-generic
linux-image-3.2.0-57-generic
linux-image-3.2.0-58-generic
linux-image-3.2.0-61-generic
linux-image-3.2.0-63-generic
linux-image-3.2.0-64-generic

This all assumes that the list of kernels in list.txt is in a sorted format.

Additional tips

If you're interested, I wrote up a A to this Q&A titled: How to programmatically determine the highest version kernel RPM installed? where I show how you can parse out versions of kernels using sort -V.

1

As you have mentioned the list, I assume it is in some file. Nevertheless, the command can be easily modified.

A simpler approach would be,

current_ver=$(uname -r)
awk "/$current_ver/{y=1;next}y" list

The current_ver variable stores the current kernel version. The awk command gets the output after the current version.

P.S:

I am not pretty well versed in awk. The command can sure be further enhanced :)

1

Since we are definitely working with linux here you might use GNU ls to -version sort results. Considering that and that your kernel file-names are unlikely to contain any weird characters you could do:

ls -1v /boot/linux-image* | grep "$(uname -r)" -B1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .