Kyle Brandt

Original computing and productivity articles by a Linux administrator

Archive for June, 2008

pyGnomeFind: A GUI frontend to GNU Find

with one comment

I have written a graphical front end to the GNU find utility called pyGnomeFind. It does not include all of the features of the actual command line utility but does cover most of the essentials. The current version is a testing/preview version. It was written using Python, pyGtk, and Glade. You can get a copy here, and at the bottom is the obligatory screen shot. Right now the code has a haphazard structure so I need to re factor it. Please do let me know if you see anything wrong with a generated find command. Lastly, on a Debian/Ubuntu system you might need to run ‘apt-get install python-gtk2 python-glade2′ to get it to work.

Update 1: Version 0.2, includes the ability to execute the command and display the results in a window, and also a reworking of the interface so sections (i.e time and size) are collapsible.

Update 2: Version 0.3, the user is now able to take parts of the command and group them for use with and/or logic. Next I will be looking into some possible interface reworking, the ability to have multiples of some of the options that currently lack it, and threading so a find command that is executed that takes a long time does not lock up the GUI.

Update 3: Version 0.3.5, Added multiples of many of the tests where there was only one. Also started to use the Glade 3 interface designer (was using 2).

pyGnomeFind version 0.1:

Written by Kyle

June 22nd, 2008 at 5:45 am

Posted in Linux, Programming, Python

Tagged with , ,

Quick Tip: Thinking about Bash Redirection and File Descriptors

without comments

A common question that comes up from people new to bash scripting is: “How do I redirect standard error to standard out?” There are a few ways to write this but the clearest way in my opinion is “command 2>&1″. File descriptor 2 is standard error, and 1 is standard out. So “2>&1″ reads in the form of the question: “File descriptor 2 is being redirected to file descriptor 1.”

However, I think that question itself causes confusion. I don’t think the phrase should be “redirecting standard error to standard out.” Rather, you are redirecting standard error to where standard out points to. You can also think “the file descriptors describe the files they point too.” To see this behavior, you can run ‘xclock 1> ~/scrap/foo 2>&1 ‘. What this does is redirect standard error to where standard out points to, and then redirects standard output to ‘~/scrap/foo’. If you run the following: ‘ls -l /proc/pid_of_xclock/fd’, you will see the above described behavior in action.

Written by Kyle

June 16th, 2008 at 7:57 am

Learning while Reviewing: Python and Subnetting

without comments

I am currently learning Python, but I also needed to review subnetting. I have found that one of the best ways to stretch my synapses is to combine learning something new with reviewing something that I learned a while back.

To accomplish my review while still learning a new skill I decided to write a simple program that contains functions for the tasks involved in subnetting. Basically, I aimed to write a mediocre ipcalc. I also decided to write these functions in the way that I would think of them, not necessarily the most efficient way to program them. For example, see this solution vs. mine for converting decimal to binary. My functions include decimal to binary conversion, getting relevant information from a subnet mask, and getting the network id of an IP using a subnet mask. You can get the full code of the following examples here.

The first function, ip_to_binary, is pretty straight forward. It works the same way a person is usually taught to convert IP octets into binary (a.k.a base 2). It generates a list of the powers of two, up to 2^7 as a reference. It then iterates over each octet of the IP address. Within that iteration it iterates over the 2^7 list. If it can subtract the octet from the value in the list, it does so and records a 1 and then subtracts the value of the list from the octet; the program then proceeds with another iteration. If it can’t subtract the value then it just records a 0.

The second function, get_subnet_info, uses the previous function to convert a subnet mask to binary. It then counts the number of masked bits (1) and unmasked bits (o). Finally it uses these counts to find out information such as how many subnets there are, how many hosts are in each subnet, what the CIDR notation is, and what the block size is in decimal for the octet of interest (the one that isn’t 0 or 255). See Sybex CCNA study guide, sixth edition, page 119 for more information on these operations.

The third function just prints the information returned from get_subnet_info in a helpful format.

The last function, get_network_id, takes an IP and subnet mask to get the network id number. This is done by iterating over each octet in the IP and the mask in parallel and performing bitwise AND between the two octets in each iteration. See “The ‘mask’ in subnet mask’ section in IP subnetting made easy to find out how this works.

Learning something new at the same time as reviewing something old creates an energy and agility in my thought process. This combination leads me to make connections between different areas of study. It also makes me learn new information while accessing my memory. Lastly, writing about it clarifies my thoughts and acts as a short term review to wrap it all up.

Written by Kyle

June 9th, 2008 at 11:15 am

Bash: Getting Command Line Columns to Line up

with 3 comments

Update: David Harding pointed out in his comment to this post that the column utility does exactly this. Therefore, the following is really just an academic exercise.

In my last post I showed how to get columns outputted in the command line to line up using python. In this post I am going to show you how to do it with Bash scripts (I think you could also use this same method with python using calls to the shell). Instead of padding the columns with spaces as I did in my previous post, this time we use a tab character for the delimiter and manually set the tab stops in the terminal itself. Since this is the terminal, not the shell, this will work with other shells as well (such as my favorite interactive shell, Zsh).

There is example code at the bottom. Instead of creating functions as I did with my previous post I have kept this example pretty tedious (repetitive code etc) to lessen the levels of abstraction and make the example a little clearer.

The first part finds the max width of each column of a text file. This example has 4 columns and a while loop that splits them on the tab character by setting the IFS ( Input Field Separator ) variable to tab for the loop only. Each iteration of the while loop remembers the value of each column; it saves the value in the $max# variable if the length was larger then the previous iteration ( the variable substitution ${#variable} returns the length of the variable ).

The second part, after the while loop, finds where the tab stops should be placed. The setterm command with the -tabs switch sets tab stops at absolute positions up to 160 ( each argument specifies where the tab stop is relative to the start of the line, not relative to the previous tab stop ) . So for this example, the second tab stop position is found by adding the width of the first column to the width of second column — this gives us the position relative to the start of line. Lastly, after setting the tab stops the file is displayed on the terminal with cat.

A caveat is that it is hard to find out what to set $TERM to. On my machine, when I am in screen session $TERM is equal to ’screen’, but this doesn’t work with setterm, I have to set TERM to ‘linux’.

I hope this helps someone when creating their next command line utility that uses columns.

Written by Kyle

June 6th, 2008 at 7:52 am

Getting Command Line Columns to Line up with Python

with one comment

I created a solution for a program I am writing that makes columns line up when outputted to the command line. I am new to Python, and am hoping I might get some input on this topic.

In the text file that the program reads, the fields (columns) are delimited by ‘$’ and the records (lines) are delimited by newlines ‘\n’. So one line looks like: 1$foo$bar

I broke this task into two separate functions. The first function, opt_output, finds the max length of each column and returns a list such as [1, 23, 14] where 1 is the max width of the first column, 23 is the max length of the second column etc. This function takes a list object as an argument; that list is the file described above with one record as an object in the list. It then iterates over the list, splitting each record into a list on its delimiter. Then the function iterates over an individual record, saving the length of each item if the length is larger then the the length of the equivalent column in previous record. This is of course clearer in the code itself:

The Second function, print_line, takes one record as a list object (already split into items) and the value returned from the previous function. It then uses the values returned from opt_output and pads each item in the list with spaces. The number of spaces to pad it with is figured out by subtracting the length of the item from the max length of the column that was found by the previous function. Finally, it rejoins the list with the delimiter ‘$’ and then splits the list again using the padded spaces as the delimiter for each column:

When calling these functions I record the value of the first function in a variable so it does not have to iterate over the list over and over again. The print line function is called for each line in the file when outputting file to the screen. As long as there is a fixed width font everything lines up nicely in the terminal.

Written by Kyle

June 4th, 2008 at 7:04 am