I’m wondering if someone can help me to understand the following command. The purpose of this command is to purge the old kernels however I would like to understand the syntax:
dpkg -l 'linux-*' | sed '/^ii/!d;/'"$(uname -r | sed "s/\(.*\)-\([^0-9]\+\)/\1/")"'/d;s/^[^ ]* [^ ]* \([^ ]*\).*/\1/;/[0-9]/!d' | xargs sudo apt-get -y purge
This is what I have so far:
dpkg -l ‘linux-*’ – list packages contain “linux-*” pattern
sed ‘/^ii/!d;/’… – find the lines starting with ii but don’t contain d;
“$(uname -r | sed “s/(.*)-([^0-9]+)/\1/”)”‘/d – command substitution to list the current kernel and extract only the number from the version, sed “s/(.*)… – search for any number of characters, …([^0-9]… – starting with numbers 0-9, I don’t understand this bit: …+)/\1/…
I’m completely lost with this one:
s/^[^ ]* [^ ]* ([^ ])./\1/;/[0-9]/!d’ – is it looking for empty characters starting the string?
Regards
So, we have one long
sedcommand here to analyse:It’s fed a list of packages matching ‘linux-*’ in
dpkgsyntax, which is a bit cryptic to start with, but the start of the lines indicates information about the package state.The
sedcommand itself is quite long (though I’m guilty of worse!), but fairly straightforward, with no looping or complications.sed, as the Fine Manual would tell you, accepts programs as a list of commands separated by semi-colons. So, the givensedprogram has four commands.Firstly, ‘/^ii/!d’. We delete lines which don’t start with ‘ii’. Simple enough. We’re looking for installed packages to remove.
Secondly, ‘/'”$(uname -r | sed “s/(.*)-([^0-9]+)/\1/”)”‘/d’. This is a command-line within a command-line (using
bash‘s $() syntax), so we’ll work from the inside out. The aim is clearly to filter out from the list of packages our currently running kernel so we don’t remove it. The output fromuname -rdoesn’t quite match the debian package names, so it’s filtered from something like “3.0.0-generic” to just “3.0.0”. The innersedcommand, “s/(.*)-([^0-9]+)/\1/”)”, is just a simple regular expression search-and-replace that cuts off the end of the input after any hyphen. After $() substitution, the outersedcommand looks like this ‘/3.0.0/d’ (depending on kernel you’re running). It just deletes lines that contain your current kernel version number.Thirdly and fourthly, ‘s/^[^ ]* [^ ]* ([^ ])./\1/’ and ‘/[0-9]/!d’ are the final filters. The first one again is a basic search-and-replace (it would be much clearer done in
awk) that extracts the third field of the line, which will be the package name, and after that we delete lines which don’t contain a digit (or else we’d remove the meta-packages that pull in the kernel upgrades).Finally,
xargsgrabs its input line-by-line and runs the command you pass it on each line, with the line appended to its arguments. So, we remove each package we’ve found.