Matthew Daly's Blog

I'm a web developer in Norfolk. This is my blog...

29th October 2010 8:49 pm

Deleting Unwanted Vim Swap Files Using Perl

Yesterday I realised that I had somehow managed to scatter Vim swap files all across the Dropbox folder I use to share Perl and Python scripts I’d written between several computers, and it would be a good idea to clear them up. I didn’t like the idea of using grep to search for them and manually deleting them, so I decided this was the ideal opportunity to write a Perl script to do it for me!

I came up with the following:

#!/usr/bin/perl -w
use strict;
use Cwd;
sub searchDir
{
# Subroutine to scan a directory looking for Vim swap files
# Get directory to read and current directory
my $readdir = shift;
my $startdir = cwd();
# Change directory to the target one
chdir($readdir) or die "Unable to open $readdir! $!\n";
print "Scanning contents of directory $startdir\n";
# Open the directory and grab the names of all the files and folders in it
opendir(DIR, ".") or die "Unable to open current directory! $!\n";
my @entries = readdir(DIR) or die "Unable to read directory! $!\n";
closedir(DIR);
# Loop through the files and folders in the directory
foreach my $entry (@entries)
{
# Skip this one and the one above it in the filesystem hierarchy
next if($entry eq ".");
next if($entry eq "..");
# If a file is a directory, call the searchDir subroutine recursively in order to scan it
if(-d $entry)
{
searchDir($entry);
next;
}
# Use a regular expression to check to see if the current file starts with a period, and ends with .swp - if it does, it's a Vim swap file
if($entry =~ m/^\..*\.swp$/)
{
# Inform the user that a Vim swap file has been found and print out the path to it
print "Found a Vim swap file!\n";
my $swppath = cwd();
print "It's the file $entry in $swppath.\n";
my $fullpath = $swppath . "/" . $entry;
print "The full path is $fullpath.\n";
# Prompt the user to delete the file
print "Do you wish to delete this file? (Y/N)\t";
chomp(my $reply = );
if($reply =~ m/y/i)
{
print "Deleting $fullpath...\n";
unlink($fullpath);
}
}
}
chdir($startdir);
}
# Get directory to begin the search
print "Enter directory to start search: ";
chomp(my $beginSearch = );
# call searchDir to start the search
searchDir($beginSearch);

Thankfully, I’ve now discovered the Preserve Code Formatting plugin for WordPress, which seems to do a good job at making the code look presentable!

This isn’t perfect - it uses recursion to examine subdirectories, and when I ran it on my /home folder it somehow wound up in /sys on my Ubuntu machine and I ended up getting a deep recursion warning (a little research suggests this happens when it goes over 100 directories in). However, it seems to work fine for scanning individual folders in my /home directory, and that’s all I really wanted anyway.

I love how Perl makes writing this kind of simple script so easy. It’s a great language for that kind of systems administration task.

27th October 2010 12:15 am

A Couple of Things I Love About Perl

In the time that I’ve been learning Perl, I’ve slowly grown to appreciate the strengths of the language more and more. There’s two things in particular that I like about Perl. Once that I really don’t think anyone is going to be surprised by is CPAN. It’s a fantastic resource - there are a huge quantity of Perl modules available for virtually any task under the sun, and they’re incredibly useful.

The other is just how good the documentation is - I’ve never considered myself to be someone who learns terribly well from Unix man pages, but perldoc seems to have very good documentation indeed, including that for CPAN modules. Also, it helps that if you don’t do well with the man page format, you have the option of running podwebserver and getting the documentation formatted as web pages.

To give an example, I’m particularly interested in all kinds of network programming, be it web development, IRC, Jabber or whatever, and I’d heard of the Net::IRC module so I decided to start using it to create a simple IRC bot (yes, I know I should really be using POE::Component::IRC instead!). Using the information gleaned from perldoc Net::IRC it was easy to get started writing a bot, and I’ve now come up with the following simple bot:

#!/usr/bin/perl -w
use strict;
use Net::IRC;
my $irc = new Net::IRC;
my $nick = "mattsbot";
my $server = "irc.freenode.net";
my $channel = "#botpark";
my $port = 6667;
my $ircname = "My wonderful bot";
my $owner = "mattbd";
sub on_connect
{
my $self = shift;
print "Joining $channel\n";
$self->join($channel);
$self->privmsg($channel,"Ready to go!");
}
sub on_disconnect
{
my $self = shift;
$self->join($channel);
$self->privmsg($channel, "Sorry about that - dropped out for a sec.");
}
sub on_join
{
# Get the connection and event objects
my ($conn, $event) = @_;
# Get the nick that just joined
my $newnick = $event->{nick};
# Greet the new nick
$conn->privmsg($channel, "Hello, $newnick! I'm a greeting bot!");
}
sub on_msg
{
# Get the connection and event objects
my ($conn, $event) = @_;
# Get nick of messaging user
my $messager = $event->{nick};
# Respond negatively
$conn->privmsg($messager, "Sorry, I'm just a bot. Please don't message me!");
}
sub on_public
{
# Get the connection and event objects
my ($conn, $event) = @_;
# Get nick of messaging user
my $messager = $event->{nick};
# Get text of message
my $text = $event->{args}[0];
# Check to see if text contains name of bot - if so message the user negatively
if($text =~ m/$nick/)
{
$conn->privmsg($channel, "Sorry, $messager,I'm just a simple bot!");
}
}
my $conn = $irc->newconn(Nick =>$nick,Server=>$server,Port=>$port,Ircname=>$ircname);
$conn->add_global_handler('376', \&on;_connect);
$conn->add_global_handler('disconnect', \&on;_disconnect);
$conn->add_global_handler('msg', \&on;_msg);
$conn->add_global_handler('join', \&on;_join);
$conn->add_global_handler('msg', \&on;_msg);
$conn->add_global_handler('public', \&on;_public);
$irc->start();

Now, this bot isn’t exactly hugely capable - all it does is greet new joiners, and tell you to leave it alone if you try to talk to it, but it was pretty easy to code it, thanks to the documentation, and it’s a good base to build on. From here, it’s easy to extend the on_public and on_msg subroutines to deal with other messages - for instance, I could use a regular expression to look for “!respond” in the text of the message and if it’s found, respond with any appropriate text.

I’ve hard-coded the appropriate details into the script in this case to make it quicker and easier to test it, but it would be trivial to change it to either accept settings passed as arguments from the command line, or have it grab these from a separate text file.

My initial doubts about Perl are really wearing off. It’s a powerful language and one that, now I’ve picked up the basic syntax, I’m having little trouble getting work done with.

19th October 2010 2:52 pm

I Passed!

Just a short post to say that today I did my CIW Perl Fundamentals exam, and passed it. Glad that’s out of the way!

16th October 2010 9:11 pm

Another Perl Snippet...

Here’s another simple Perl program I thought I’d share. It’s a very simple app for recording notes from the shell. As pasting the last one into WordPress didn’t work too well, it’s on my Dropbox account instead. I’ve used SQLite as the backend for the database (a no-brainer - I really like SQLite for little quick-and-dirty scripts like this) and it works pretty well.

At some point I may go back to this basic concept and expand on it a little - it would make sense to add a GUI to it, either by using a graphical toolkit such as Tk or turning it into a web app. I also like the idea of adapting it to use a non-relational database - something like CouchDB perhaps.

15th October 2010 8:39 pm

Getting Work Done With Perl

After my initial struggles with Perl, I now think I’m really starting to get to grips with the language. I generally find it a pain when you have to learn by building small but basically useless scripts - I always do best when building something useful.

As one of the exercises for my studies I had to open a database connection to a Microsoft Access database, but I wanted to do the exercise in Ubuntu (I’ve always preferred using Unix-like operating systems for programming, and thanks to apt-get it’s a lot less grief installing additional libraries and modules as you need them) and couldn’t get Perl to connect to the database properly, so I resolved to export it to either MySQL or SQLite.

I was able to export it to MySQL in the end using mdbtools, but I wasn’t entirely happy with the end result. I resorted to re-exporting the data as a CSV file, then resolved to write a small Perl script to read the file, parse it using a regular expression to obtain the necessary information, then insert it into a new SQLite database.

Here’s what I came up with:

#!/usr/bin/perl -w
use strict;
use DBI;
my $db = "dbi:SQLite:backend.db";
if (!(-e "backend.db"))
{
print "Database does not exist. Creating it...";
# Create the database
my $dbh = DBI->connect($db) or die "Error in connecting to database! $DBI::errstr";
my $createdb = $dbh->do("CREATE TABLE CARS( ID INTEGER PRIMARY KEY, YEAR INTEGER, MAKE VARCHAR(30), MODEL VARCHAR(30), COLOR VARCHAR(30), PRICE INTEGER);");
$dbh->disconnect();
}
open(READFILE, "cartable.csv");
while()
{
unless($_ =~ m/id,/)
{
m/\d+\,(\d{4})\,\"(\w+)\"\,\"(\w+)\"\,\"(\w+)\"\,\"(\d+)\"/;
my $year = $1;
my $make = $2;
my $model = $3;
my $color = $4;
my $price = $5;
my $dbh2 = DBI->connect($db) or die "Error in connecting to database! $DBI::errstr";
my $insertdb = $dbh2->do("INSERT INTO CARS (YEAR, MAKE, MODEL, COLOR, PRICE) VALUES (\"$year\", \"$make\", \"$model\", \"$color\", \"$price\");");
$dbh2->disconnect;
}
}
close(READFILE);
print "Write completed!\n";
print "To demonstrate it works, we'll run a SELECT query against the database...\n";
# Read the database
my $readdb = DBI->connect($db);
my $dbselect = $readdb->prepare("SELECT * FROM CARS;");
$dbselect->execute;
# Print the results
print "ID\tYear\tMake\tModel\tColor\tPrice\n";
while(my @row = $dbselect->fetchrow_array)
{
print "$row[0]\t$row[1]\t$row[2]\t$row[3]\t$row[4]\t$row[5]\n";
}
# Close the connection
$readdb->disconnect;

Apologies for the fact that the indentation doesn’t seem to have copied across from Vim very well (can anyone recommend a good WordPress plugin for displaying code, none of the ones I’ve tried seem to be any good?). It works well, and it’s also helped me grasp Perl’s database API better.

I think I’ve got a better idea now of what Python and Perl are best at and when to use each. Perl is a great language, but the fact that a lot of it is implicit makes it a little harder to pick up at first than Python - for instance, the default variable, which is quite a good idea, but takes a little getting used to. Its regex support is great, and I like the database API, but I would find it a lot harder to do any object-oriented programming in Perl than in Python (which I guess is why Moose exists). I’ve found Perl very useful for quick and dirty scripts and as a glue language, but for longer scripts Python seems the better choice.

Recent Posts

Writing Golden Master Tests for Laravel Applications

How Much Difference Does Adding An Index to a Database Table Make?

Searching Content With Fuse.js

Higher-order Components in React

Creating Your Own Dependency Injection Container in PHP

About me

I'm a web and mobile app developer based in Norfolk. My skillset includes Python, PHP and Javascript, and I have extensive experience working with CodeIgniter, Laravel, Zend Framework, Django, Phonegap and React.js.