PERL and BASH - Find packages with apt-cache and dpkg-query

About writing shell scripts and making the most of your shell
Forum rules
Topics in this forum are automatically closed 6 months after creation.
Locked
Anakinholland

PERL and BASH - Find packages with apt-cache and dpkg-query

Post by Anakinholland »

So,

Last weekend (and the weeks before :P) I was muzing on the fact that yum ("the apt-get for RedHat-based distros") is so much cleaner and intuitive than apt, especially the package-searching.

I put my thoughts into IRC, which gave me some answers from chattr and glebihan. With these under my arm, I intended to script something in Perl, as that's a language I really want to learn and of which I think it's stronger than just good ol' shell.

However... I didn't have the slightest idea on how to script Perl!!

Here's the shell-script that I whipped up in a just few minutes:

Code: Select all

#!/bin/bash

### Just some globals and checks to keep me sane,
### the outpout correct and the filesystem clean.

temp_good=/tmp/apt_temp_good.txt
temp_fail=/tmp/apt_temp_fail.txt

if [ -w ${temp_good} ]
then
	rm -f ${temp_good}
fi

if [ -w ${temp_fail} ]
then
	rm -f ${temp_fail}
fi

### Gotta have something to search for...

if [ -z ${1} ]
then
	echo "Give parameter to work with..."
	exit 1
fi

### Do your stuff! 

for i in `apt-cache search ${1} | awk -F " - " '{ print $1 }'`
do
	result=`dpkg-query -W ${i} 2>/dev/null`
	if [[ `echo ${result} | grep -v "No packages found matching"` == "" ]]
	then
		echo "${i}" >> ${temp_fail}
	else
		echo "${i}" >> ${temp_good}
	fi
done

### Let the user know the output.

echo "############# Installed #################"
cat ${temp_good} 2>/dev/null
echo "############# Available #################"
cat ${temp_fail} 2>/dev/null
exit 0
Wanting to do this in Perl, it took me numerous hours to achieve the same thing:

Code: Select all

#!/usr/bin/perl

#use diagnostics;

$i=0;
$j=0;
$k=0;

$ls_cmd = 'sudo apt-cache search';
$dpkg_cmd = 'dpkg-query -W 2>&1'; 

open(LS_CMD, "$ls_cmd $ARGV[0] |") or die "Can't run '$ls_cmd'\n$!\n";
while(<LS_CMD>){ 
		@fields = split (" - ",$_);
		$ls_list[$i++] = "$fields[0]" ; # save output line in the array
}

open(DPKG_CMD, "$dpkg_cmd 2>&1 @ls_list |") or die "Can't run '$dpkg_cmd'\n$!\n";
		while (<DPKG_CMD>){
			if ($_ =~ m/^No packages/){
				@package = split(/ /,$_);
				$ls_notpresent[$j++] = "$package[-1]" ;
			} else {
				$ls_output[$k++] = "$_" ;
			}
		}

print "################ Installed ############### \n";
print @ls_output;
print "################ Available ############### \n";
print @ls_notpresent;
Important note: the Perl-version is MUCH quicker, as it runs dpkg-query once with a lot of parameters, instead of running dpkg-query a lot of times with a single parameter.

I have to admit, Perl is much more complex but also much, MUCH more flexible... This example reallly makes me want to learn more!

The result of either scripts with parameter "geany" would look like this:

Code: Select all

################ Installed ############### 
geany	0.20-0ubuntu2
geany-plugins	
geany-plugins-common	
################ Available ############### 
geany-plugin-addons.
geany-plugin-codenav.
geany-plugin-doc.
geany-plugin-extrasel.
geany-plugin-gdb.
geany-plugin-gendoc.
geany-plugin-insertnum.
geany-plugin-latex.
geany-plugin-lipsum.
geany-plugin-lua.
geany-plugin-prettyprinter.
geany-plugin-prj.
geany-plugin-sendmail.
geany-plugin-shiftcolumn.
geany-plugin-spellcheck.
geany-plugin-treebrowser.
geany-plugin-updatechecker.
geany-plugin-vc.
geany-plugin-webhelper.
The shell-script will not display versions on installed packages. One thing in the Perl-version I can't get my head around is to remove the period at the end of the package-names that aren't installed...

Feel free to address any issues and mention any improvements you see!

Anakin
Last edited by LockBot on Wed Dec 28, 2022 7:16 am, edited 1 time in total.
Reason: Topic automatically closed 6 months after creation. New replies are no longer allowed.
ChickenPie4Tea

Re: PERL and BASH - Find packages with apt-cache and dpkg-qu

Post by ChickenPie4Tea »

Thanks, will come in handy,
does perl come with mint? and do you have to save the file an exstention?
I wonder why perl instead of Python?
User avatar
xenopeek
Level 25
Level 25
Posts: 29607
Joined: Wed Jul 06, 2011 3:58 am

Re: PERL and BASH - Find packages with apt-cache and dpkg-qu

Post by xenopeek »

There is a bug in your script I think. A dpkg-query -W doesn't actually report on whether or not a package is installed, just if it is known. As an example, see the following session:

Code: Select all

vincent@katya ~ $ dpkg-query -W python-nautilus
python-nautilus

vincent@katya ~ $ dpkg -s python-nautilus
Package `python-nautilus' is not installed and no info is available.
Use dpkg --info (= dpkg-deb --info) to examine archive files,
and dpkg --contents (= dpkg-deb --contents) to list their contents.

vincent@katya ~ $ dpkg -l python-nautilus
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name           Version        Description
+++-==============-==============-============================================
un  python-nautilu <none>         (no description available)
Basically, the command that you can use instead in your script would be:

Code: Select all

apt-cache -n search ${1} | cut -d' ' -f1 | paste -sd ' ' | xargs dpkg -l
Lines starting with 'ii' denote installed packages, lines starting with other characters denote packages known and with some special case, packages on stderr are found by apt-cache but as yet unknown in dpkg. Example output for running it with nautilus as pattern:

Code: Select all

Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                              Version                           Description
+++-=================================-=================================-==================================================================================
ii  libnautilus-extension1            1:2.32.2.1-0ubuntu13              libraries for nautilus components - runtime version
ii  nautilus                          1:2.32.2.1-0ubuntu13              file manager and graphical shell for GNOME
ii  nautilus-actions                  3.0.5-1                           nautilus extension to configure programs to launch
un  nautilus-cd-burner                <none>                            (no description available)
ii  nautilus-data                     1:2.32.2.1-0ubuntu13              data files for nautilus
un  nautilus-dropbox                  <none>                            (no description available)
un  nautilus-filename-repairer        <none>                            (no description available)
ii  nautilus-gksu                     2.0.2-5ubuntu2                    privilege granting extension for nautilus using gksu
un  nautilus-image-converter          <none>                            (no description available)
ii  nautilus-open-terminal            0.18-1                            nautilus plugin for opening terminals in arbitrary local paths
ii  nautilus-sendto                   2.32.0-0ubuntu1.1                 integrates Evolution and Pidgin into the Nautilus file manager
un  nautilus-sendto-empathy           <none>                            (no description available)
ii  nautilus-share                    0.7.2-14ubuntu1                   Nautilus extension to share folder using Samba
ii  nautilus-wallpaper                0.1-0ubuntu4                      Nautilus extension. Add a "set as wallpaper" entry in context menu
un  python-nautilus                   <none>                            (no description available)
No packages found matching gir1.2-nautilus-2.0.
No packages found matching libnautilus-extension-dev.
No packages found matching nautilus-dbg.
No packages found matching arkose-nautilus.
No packages found matching libnautilus-burn-dev.
No packages found matching libnautilus-burn4.
No packages found matching nautilus-arista.
No packages found matching nautilus-bzr.
No packages found matching nautilus-clamscan.
No packages found matching nautilus-ideviceinfo.
No packages found matching nautilus-pastebin.
No packages found matching nautilus-script-audio-convert.
No packages found matching nautilus-script-collection-svn.
No packages found matching nautilus-script-debug.
No packages found matching nautilus-script-manager.
No packages found matching nautilus-scripts-manager.
No packages found matching purrr.
No packages found matching rabbitvcs-nautilus.
No packages found matching tortoisehg-nautilus.
And finally, before I found the above possible bug, I had rewritten your BASH script to just the following few commands :wink: It generates the exact same output as your script, though I've added -n to apt-cache search so as to only search package names instead of the full description. Perhaps I'll rewrite it later to include my above suggestion :mrgreen:

Code: Select all

#!/bin/bash

if [[ -z $1 ]]; then
	echo "Give parameter to work with..."
	exit 1
fi

tempfile=$(tempfile)
apt-cache -n search $1 1>$tempfile 2>/dev/null
echo "############# Installed #################"
cut -d' ' -f1 $tempfile | paste -sd ' ' | xargs dpkg-query -W      2>/dev/null | cut -f1
echo "############# Available #################"
cut -d' ' -f1 $tempfile | paste -sd ' ' | xargs dpkg-query -W 2>&1  >/dev/null | sed 's/^No packages found matching //' | sed 's/.$//'
Image
mph426

Re: PERL and BASH - Find packages with apt-cache and dpkg-qu

Post by mph426 »

This is a very cool idea. I too have been stymied by the lack of command line tools to see what is and what isn't installed. I just assumed that it was due to my lack of knowledge of the "debian" way. ;) And, maybe it is.

One thing I might add that really doesn't add much to the run time but makes the output a lot easier to parse... for me anyway.

Just added the sort command.

Code: Select all

apt-cache -n search $1 | sort 1>$tempfile 2>/dev/null
I can see a ton of options being added and making this a VERY functional script. Maybe a wrapper of sorts for apt. Look out yum!! LOL
Anakinholland

Re: PERL and BASH - Find packages with apt-cache and dpkg-qu

Post by Anakinholland »

Fair points Vincent and mph :)

Will alter the script in the upcoming days, as I've made a number of changes to it myself as well.

Regards,

Anakin
Locked

Return to “Scripts & Bash”