Thursday, June 25, 2009

Sometimes ls just doesn't cut the mustard

Occasionally I want more than ls can give me.

On this occasion I required the file modification date in a specific format for a specified file. So here's a perl one-liner to give it to me.

perl -e '$mtime=(stat(@ARGV))[9];@f=(localtime($mtime))[3..5];printf "%02d/%02d/%d\n",$f[0],$f[1]+1,$f[2]+1900;' filename

This produces the date in dd/mm/yyyy format.

Just what I wanted.

Here's another similar script to get the file size

perl -e '$size=(stat(@ARGV))[7];printf "%d\n",$size;' filename

This is the information you can get from stat

0  dev     device number of filesystem
1  ino     inode number
2  mode    file mode (type and permissions)
3  nlink   number of (hard) links to the file
4  uid     numeric user ID of file's owner
5  gid     numeric group ID of file's owner
6  rdev    the device identifier (special files only)
7  size    total size of file, in bytes
8  atime   last access time in seconds since the epoch
9  mtime   last modify time in seconds since the epoch
10 ctime   inode change time in seconds since the epoch
11 blksize preferred block size for file system I/O
12 blocks  actual number of blocks allocated

Wednesday, June 24, 2009

UNIX flavours and double evaluation

When I write shell scripts (ksh) I do not like to rely on a PATH so I tend to hardcode all UNIX executables. This means that they can generally run as is using cron.

Example


CAT=/usr/bin/cat
$CAT milk



However this is not very useful when mixing UNIX variants so I have come up with this way of coding so that we can catch as many UNIX flavours as possible

# Commands
typeset -u Command
for Name in cat date grep hostname mailx mv perl ps rm
do
Command=$Name

case $Name in
grep) PathNames=/usr/xpg4/bin:/usr/bin:/bin ;;
*) PathNames=/usr/bin:/bin ;;
esac

while [[ -n $PathNames ]]
do
PathName=${PathNames%%:*}
PathNames=${PathNames#*:}

if [[ $PathName = $PathNames ]]
then
PathNames=""
fi

if [[ -x $PathName/$Name ]]
then
eval "$Command=$PathName/$Name"
break
fi
done

if [[ -z $(eval print `print \\$${Command}`) ]]
then
print -u2 "Unable to find a $Name executable"
exit 1
fi
done
The bit I like the best is that last if statement which checks that the executable was found.


The eval command tries to print out, say, $CAT to check that the CAT variable has something in it, but as CAT is the value of the variable Command we have to do some jiggery pokery to get it to parse properly.