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

Forum rules
Before you post please read this

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

Postby Anakinholland on Mon Nov 28, 2011 5:35 pm

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
Please Edit your initial post title and add [SOLVED] once your question is resolved.
User avatar
Anakinholland
Level 3
Level 3
 
Posts: 145
Joined: Sun Oct 30, 2011 8:09 am

Linux Mint is funded by ads and donations.
 

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

Postby ChickenPie4Tea on Tue Feb 07, 2012 7:28 am

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?
ChickenPie4Tea
Level 3
Level 3
 
Posts: 109
Joined: Sun Jan 22, 2012 6:44 pm

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

Postby xenopeek on Fri Feb 17, 2012 1:18 pm

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/.$//'
User avatar
xenopeek
Level 21
Level 21
 
Posts: 14967
Joined: Wed Jul 06, 2011 3:58 am
Location: The Netherlands

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

Postby mph426 on Sat Feb 18, 2012 1:20 pm

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
I'd rather have a bottle in front of me than a frontal lobotomy.
mph426
Level 1
Level 1
 
Posts: 23
Joined: Fri Dec 16, 2011 3:03 pm
Location: State of confusion

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

Postby Anakinholland on Wed Feb 22, 2012 6:41 am

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
Please Edit your initial post title and add [SOLVED] once your question is resolved.
User avatar
Anakinholland
Level 3
Level 3
 
Posts: 145
Joined: Sun Oct 30, 2011 8:09 am


Return to Scripts & Bash

Who is online

Users browsing this forum: No registered users and 2 guests