Thursday, June 25, 2009

Bash Tricks - Variable variable name

There are rare situations where you will have to use the value of a variable as another variable name, bash provides a special construct for this purpose.

Create a variable and assign a value

safeer@penguin-power:~/temp$ MY_VAR1="MY_VALUE1"

Assign the variable name "MY_VAR1" to MY_VAR2.

safeer@penguin-power:~/temp$ MY_VAR2="MY_VAR1"

Now use MY_VAR2 to print the contents of MY_VAR1

safeer@penguin-power:~/temp$ echo ${!MY_VAR2}
MY_VALUE1

Let us try with an example where command line arguments ( $1,$2,$3 etc.... ) of a script are parsed using the argument numbers (1,2,3...) taken from another variable.

safeer@penguin-power:~/temp$ cat test.sh
#!/bin/bash
for((i=1;i<=$#;i++))
do
echo ${!i};
done

safeer@penguin-power:~/temp$ ./test.sh first second third fourth
first
second
third
fourth

safeer@penguin-power:~/temp$ ./test.sh first
first

Monday, June 15, 2009

Working with files in perl

Opening a file for Read/Write/Append

You can open a file using the function open(). It takes three arguments: a file handle which is just a symbolic name of your choice for the file, a mode symbol which specifies the file operation mode in which the file should be opened, and third being the file to be opened itself.

Mode operators are as given below.

< : Read - Default if a mode is not specified at all.
> : Write -File is Created if not existing else Overwrites.
>> : Append - creates file if not existing.

If you want to combine read and write, prepend a "+" to the modes.

+< : Read/Write,Don't create file,Overwrites existing.
+> : Read/Write,Create file if not existing, else Overwrite.
+>> : Read/Append,Create file if not existing, no Overwrite

Let us take an example.

open ( MY_FILE_HANDLE,"<","/home/safeer/docs/accounts.txt");

This will open the file "/home/safeer/docs/accounts.txt" for reading and will be accessible through the file handle MY_FILE_HANDLE. We can use this handle to read data from the actual file.

The second and third arguments for open() can be combined into a single string as "< /home/safeer/docs/accounts.txt". In the case of mode, it is OK even if you skip the "<" symbol - since read is the default mode. So,

open ( MY_FILE_HANDLE,"<","/home/safeer/docs/accounts.txt");

open ( MY_FILE_HANDLE,"< /home/safeer/docs/accounts.txt");
open ( MY_FILE_HANDLE,"/home/safeer/docs/accounts.txt");

are all the same.

If you want to open this file for writing, use

open ( MY_FILE_HANDLE,">","/home/safeer/docs/accounts.txt"); OR
open ( MY_FILE_HANDLE,"> /home/safeer/docs/accounts.txt");

Reading data from a file

Open the file in read mode

open ( MY_FILE_HANDLE,"< /home/safeer/docs/accounts.txt");

You can assign the the entire file content to an array variable where each element of the array will correspond to a single line in the file.

@acounts_data = <MY_FILE_HANDLE> ;

But this can be memory intensive if the file you are opening is very large. A better way is to read file line by line and process it as follows.

while ( $line = <MY_FILE_HANDLE> ){
#Process $line here
}

In every iteration $line will contain a single line of the file. Note that the last character of the $line will be newline (\n), so you may want to chomp $line before processing it. The following code will be equivalent to printing the file contents.

while ( $line = <MY_FILE_HANDLE> ){
chomp ($line);
print"$line\n";
}

Write/Append to a file:

We use print command to write/append (depends on the mode in which the file is opened) to a file.

Syntax: print $FILEHANDLE $STRING;

To start writing, first open file in write mode and then print using the file handle obtained from open().

open ( MY_FILE_HANDLE,"> /home/safeer/docs/newaccounts.txt");
$my_account = "safeer:/home/safeer/:usr/bin/bash" ;
print MY_FILE_HANDLE "$my_account\n";

Alternatively, write directly without using variable:

print MY_FILE_HANDLE "safeer:/home/safeer/:usr/bin/bash\n" ;

If the file was opened in append mode ( ">>" ) the string would have been appended to the end of file.

open ( MY_FILE_HANDLE,">> /home/safeer/docs/accounts.txt");
print MY_FILE_HANDLE "safeer:/home/safeer/:usr/bin/bash\n" ;

Closing the file

any file that is opened should be closed once the purpose of open is over.
close (MY_FILE_HANDLE);

Monday, June 1, 2009

Extracting .CAB files in Linux

First of all, what is .cab files?

From Wikipedia:

CAB is the Microsoft Windows native compressed archive format. It supports compression and digital signing, and is used in a variety of Microsoft installation engines: Setup API, Device Installer, AdvPack (for the installation of ActiveX components from Internet Explorer) and Windows Installer.

It was originally called Diamond. Its .CAB file extension and overall file format name comes from word cabinet, internally used by Microsoft tools dealing with CAB files to reference such files.

I got a couple of resume templates from Microsoft Web Site, but the downloaded copies where in .cab format. So googled to find a way to extract them and learned that there is something called "cabextract".

On my Ubuntu box:

safeer@penguinpower:~/Desktop/PPTS$ sudo apt-cache search cabextract
cabextract - a program to extract Microsoft Cabinet files
liborange-dev - development libraries for liborange
liborange0 - library to extract CAB files from self-extracting installers
orange - extracts CAB files from self-extracting installers
safeer@penguinpower:~/Desktop/PPTS$ sudo apt-get install cabextract

RPM based distros can get the package from Dag Wieers' Repositories (if they don't have a native package).

And then, extracted the cab files without errors.

safeer@penguinpower:~/Desktop/PPTS$
cabextract 06199720.cab
06199720.cab: WARNING; possible 6960 extra bytes at end of file.
Extracting cabinet: 06199720.cab
extracting 06199720.dot
extracting content.inf

All done, no errors.
safeer@penguinpower:~/Desktop/PPTS$ cabextract 10168650.cab
10168650.cab: WARNING; possible 1024 extra bytes at end of file.
Extracting cabinet: 10168650.cab
extracting 10168650.dotx
extracting content.inf

All done, no errors.

The extracted files where in good shape and I was able to open them in Open Office.