Showing posts with label Windows-utilities. Show all posts
Showing posts with label Windows-utilities. Show all posts

Sunday, April 9, 2017

Digital Clock created in FreePascal / Lazarus

By Vasudev Ram

Some months ago I created this digital clock in Free Pascal / Lazarus on Windows, in my copious free time. It's simple, without any frills, but works well for me. I have been using it daily as the Windows clock utility I use on my PC to check the current time whenever I need to [1]. Here is a screenshot of this clock:



[1] I do wear a watch (digital, natch :) and have a mobile phone which shows the time and even has a clock app, but see:

A simple alarm clock in Python (command-line)

and

Jal-Tarang, and a musical alarm clock in Python

I usually run it (this latest clock) manually at PC startup (it's called DC, so I just have to type that and Enter). (It could be put into some Windows script or folder so that it starts automatically.) To see the clock, I just have to Alt-Tab over to it, or click on it in the Windows taskbar. In fact, even if I just hover my mouse over its icon in the taskbar, I can see the clock and the current time that it shows - and watch it changing too, right there :)

- Vasudev Ram - Online Python training and consulting

Get updates (via Gumroad) on my forthcoming apps and content.

Jump to posts: Python * DLang * xtopdf

Subscribe to my blog by email

My ActiveState Code recipes

Follow me on: LinkedIn * Twitter

Are you a blogger with some traffic? Get Convertkit:

Email marketing for professional bloggers



Saturday, February 11, 2017

tp, a simple text pager in Python

By Vasudev Ram

Yesterday I got this idea of writing a simple text file pager in Python.

Here it is, in file tp.py:
'''
tp.py
Purpose: A simple text pager.
Version: 0.1
Platform: Windows-only.
Can be adapted for Unix using tty / termios calls.
Only the use of msvcrt.getch() needs to be changed.
Author: Vasudev Ram
Copyright 2017 Vasudev Ram
Web site: https://vasudevram.github.io
Blog: https://jugad2.blogspot.com
Product store: https://gumroad.com/vasudevram
'''

import sys
import string
from msvcrt import getch

def pager(in_fil=sys.stdin, lines_per_page=10, quit_key='q'):
    assert lines_per_page > 1 and lines_per_page == int(lines_per_page)
    assert len(quit_key) == 1 and \
        quit_key in (string.ascii_letters + string.digits)
    lin_ctr = 0
    for lin in in_fil:
        sys.stdout.write(lin)
        lin_ctr += 1
        if lin_ctr >= lines_per_page:
            c = getch().lower()
            if c == quit_key.lower():
                break
            else:
                lin_ctr = 0

def main():
    try:
        sa, lsa = sys.argv, len(sys.argv)
        if lsa == 1:
            pager()
        elif lsa == 2:
            with open(sa[1], "r") as in_fil:
                pager(in_fil)
        else:
            sys.stderr.write
            ("Only one input file allowed in this version")
                    
    except IOError as ioe:
        sys.stderr.write("Caught IOError: {}".format(repr(ioe)))
        sys.exit(1)

    except Exception as e:
        sys.stderr.write("Caught Exception: {}".format(repr(e)))
        sys.exit(1)

if __name__ == '__main__':
    main()
I added a couple of assertions for sanity checking.

The logic of the program is fairly straightforward:

- open (for reading) the filename given as command line argument, or just read (the already-open) sys.stdin
- loop over the lines of the file, lines-per-page lines at a time
- read a character from the keyboard (without waiting for Enter, hence the use of msvcrt.getch [1])
- if it is the quit key, quit, else reset line counter and print another batch of lines
- do error handling as needed

[1] The msvcrt module is on Windows only, but there are ways to get equivalent functionality on Unixen; google for phrases like "reading a keypress on Unix without waiting for Enter", and look up Unix terms like tty, termios, curses, cbreak, etc.

And here are two runs of the program that dogfood it, one directly with a file (the program itself) as a command-line argument, and the other with the program at the end of a pipeline; output is not shown since it is the same as the input file, in both cases; you just have to press some key (other than q (which makes it quit), repeatedly, to page through the content):
$ python tp.py tp.py
$type tp.py | python tp.py

I could have golfed the code a bit, but chose not to, in the interest of the Zen of Python. Heck, Python is already Zen enough.

- Vasudev Ram - Online Python training and consulting

Get updates (via Gumroad) on my forthcoming apps and content.

Jump to posts: Python * DLang * xtopdf

Subscribe to my blog by email

My ActiveState Code recipes

Follow me on: LinkedIn * Twitter

Managed WordPress Hosting by FlyWheel



Sunday, January 8, 2017

An Unix seq-like utility in Python

By Vasudev Ram


Due to a chain (or sequence - pun intended :) of thoughts, I got the idea of writing a simple version of the Unix seq utility (command-line) in Python. (Some Unix versions have a similar command called jot.)

Note: I wrote this program just for fun. As the seq Wikipedia page says, modern versions of bash can do the work of seq. But this program may still be useful on Windows - not sure if the CMD shell has seq-like functionality or not. PowerShell probably has it, is my guess.)

The seq command lets you specify one or two or three numbers as command-line arguments (some of which are optional): the start, stop and step values, and it outputs all numbers in that range and with that step between them (default step is 1). I have not tried to exactly emulate seq, instead I've written my own version. One difference is that mine does not support the step argument (so it can only be 1), at least in this version. That can be added later. Another is that I print the numbers with spaces in between them, not newlines. Another is that I don't support floating-point numbers in this version (again, can be added).

The seq command has more uses than the above description might suggest (in fact, it is mainly used for other things than just printing a sequence of numbers - after all, who would have a need to do that much). Here is one example, on Unix (from the Wikipedia article about seq):
# Remove file1 through file17:
for n in `seq 17`
do
    rm file$n
done
Note that those are backquotes or grave accents around seq 17 in the above code snippet. It uses sh / bash syntax, so requires one of them, or a compatible shell.

Here is the code for seq1.py:
'''
seq1.py
Purpose: To act somewhat like the Unix seq command.
Author: Vasudev Ram
Copyright 2017 Vasudev Ram
Web site: https://vasudevram.github.io
Blog: https://jugad2.blogspot.com
Product store: https://gumroad.com/vasudevram
'''

import sys

def main():
    sa, lsa = sys.argv, len(sys.argv)
    if lsa < 2:
        sys.exit(1)
    try:
        start = 1
        if lsa == 2:
            end = int(sa[1])
        elif lsa == 3:
            start = int(sa[1])
            end = int(sa[2])
        else: # lsa > 3
            sys.exit(1)
    except ValueError as ve:
        sys.exit(1)

    for num in xrange(start, end + 1):
        print num, 
    sys.exit(0)
    
if __name__ == '__main__':
    main()
And here are a few runs of seq1.py, and the output of each run, below:
$ py -2 seq1.py

$ py -2 seq1.py 1
1

$ py -2 seq1.py 2
1 2

$ py -2 seq1.py 3
1 2 3

$ py -2 seq1.py 1 1
1

$ py -2 seq1.py 1 2
1 2

$ py -2 seq1.py 1 3
1 2 3

$ py -2 seq1.py 4
1 2 3 4

$ py -2 seq1.py 1 4
1 2 3 4

$ py -2 seq1.py 2 2
2

$ py -2 seq1.py 5 3

$ py -2 seq1.py -6 -2
-6 -5 -4 -3 -2

$ py -2 seq1.py -4 -0
-4 -3 -2 -1 0

$ py -2 seq1.py -5 5
-5 -4 -3 -2 -1 0 1 2 3 4 5

There are many other possible uses for seq, if one uses one's imagination, such as rapidly generating various filenames or directory names, with numbers in them (as a prefix, suffix or in the middle), for testing or other purposes, etc.

- Enjoy.

- Vasudev Ram - Online Python training and consulting

Get updates (via Gumroad) on my forthcoming apps and content.

Jump to posts: Python * DLang * xtopdf

Subscribe to my blog by email

My ActiveState Code recipes

Follow me on: LinkedIn * Twitter

Managed WordPress Hosting by FlyWheel



Sunday, November 13, 2016

Trapping KeyboardInterrupt and EOFError for program cleanup

By Vasudev Ram

Ctrl-C and Ctrl-Z handling

I had written this small Python utility for my own use, to show the ASCII code for any input character typed at the keyboard. Since it was a quick utility, I was initially just using Ctrl-C to exit the program. But that leaves behind a messy traceback, so I thought of trapping the exceptions KeyboardInterrupt (raised by Ctrl-C) and EOFError (raised by Ctrl-Z). With that, the program now exits cleanly on typing either of those keys.

Here is the resulting utility, char_to_ascii_code.py:
from __future__ import print_function
"""
char_to_ascii_code.py
Purpose: Show ASCII code for a given character, interactively, 
in a loop. Show trapping of KeyboardInterrupt and EOFError exceptions.
Author: Vasudev Ram
Web site: https://vasudevram.github.io
Blog: https://jugad2.blogspot.com
Product store: https://gumroad.com/vasudevram
"""

print("This program shows the ASCII code for any given ASCII character.")
print("Exit the program by pressing Ctrl-C or Ctrl-Z.")
print()

while True:
    try:
        c = raw_input( \
        "Enter an ASCII character to see its ASCII code: ")
        if len(c) != 1:
            print("Error: need a string of length 1; retry.")
            continue
        print("Character:", c)
        print("Code:", ord(c))
    except KeyboardInterrupt as ki:
        print("Caught:", repr(ki))
        print("Exiting.")
        break
    except EOFError as eofe:
        print("Caught:", repr(eofe))
        print("Exiting.")
        break
Here is a sample run, that shows the ASCII codes for the comma, tab and pipe characters, which are commonly used as field delimiters in Delimiter-Separated Value (DSV) files.
$ python char_to_ascii_code.py
This program shows the ASCII code for any given ASCII character.
Exit the program by pressing Ctrl-C or Ctrl-Z.

Enter an ASCII character to see its ASCII code, or Ctrl-C to exit: ,
Character: ,
Code: 44
Enter an ASCII character to see its ASCII code, or Ctrl-C to exit:
Character:
Code: 9
Enter an ASCII character to see its ASCII code, or Ctrl-C to exit: |
Character: |
Code: 124
Enter an ASCII character to see its ASCII code, or Ctrl-C to exit: 
Caught: KeyboardInterrupt()
Exiting.
$
I pressed the Ctrl-C key combination to exit the program. Ctrl-C does not show on the screen, but the exception handler for it is activated, and prints the last message above.

Another run shows a few more codes and the trapping of the Ctrl-Z key combination.
$ python char_to_ascii_code.py
This program shows the ASCII code for any given ASCII character.
Exit the program by pressing Ctrl-C or Ctrl-Z.

Enter an ASCII character to see its ASCII code, or Ctrl-C to exit: !
Character: !
Code: 33
Enter an ASCII character to see its ASCII code, or Ctrl-C to exit: ~
Character: ~
Code: 126
Enter an ASCII character to see its ASCII code, or Ctrl-C to exit: ^Z
Caught: EOFError()
Exiting.

- Vasudev Ram - Online Python training and consulting

Get updates on my software products / ebooks / courses.

Jump to posts: Python   DLang   xtopdf

Subscribe to my blog by email

My ActiveState recipes



Friday, October 14, 2016

Command line D utility - find files matching a pattern under a directory

By Vasudev Ram

Hi readers,

I wrote this utility in D recently, to find files matching a pattern (a wildcard) under a specified directory. Here is the program, find_files.d:
/************************************************************************
find_files.d
Author: Vasudev Ram
Compile with Digital Mars D compiler using the command:
dmd find_files.d
Usage: find_files dir patt
Finds files under directory 'dir' that match file wildcard 
pattern 'patt'.
The usual file wildcard patterns that an OS like Windows or 
Linux supports, such as *.txt, budget*.xls, my_files*, etc.,
are supported.
Copyright 2016 Vasudev Ram
Web site: https://vasudevram.github.io
Blog: http://jugad2.blogspot.com
Product updates: https://gumroad.com/vasudevram/follow
************************************************************************/

import std.stdio; 
import std.file;

string __version__ = "0.1";

void usage(string[] args) {
    debug {
        stderr.write("You gave the command: ");
        foreach(arg; args)
            stderr.write(arg, " ");
        stderr.writeln;
    }
    
    stderr.writeln(args[0], " (Find Files) v", __version__);
    stderr.writeln("Copyright 2016 Vasudev Ram" ~
    " - https://vasudevram.github.io");
    stderr.writeln("Usage: ", args[0], " dir pattern");
    stderr.writeln("Recursively find filenames, under directory 'dir', ");
    stderr.writeln("that match the literal or wildcard string 'pattern'.");
}

int main(string[] args) {

    // Check for and get correct command-line arguments.
    if (args.length != 3) {
        usage(args);
        return 1;
    }
    auto top_dir = args[1];
    if (!exists(top_dir) || !isDir(top_dir)) {
        stderr.writeln("The name ", top_dir, 
        " does not exist or is not a directory.");
        usage(args);
        return 1;
    }
    auto pattern = args[2];

    try {
        debug writeln(args[0], ": Finding files under directory: ", 
        top_dir, " that match pattern: ", pattern);
        foreach (de; dirEntries(top_dir, pattern, SpanMode.breadth)) {
            writeln(de.name);
        }
    }
    catch (Exception e) {
        stderr.writeln("Caught Exception: msg = ", e.msg);
        return 1;
    }
    return 0;
}
Compile command:
$ dmd -offf find_files.d
The -of flag is for "output file", and is used to specify the .EXE file to be created. The command creates ff.exe on Windows).

Compile command to create debug version (the statements prefixed 'debug' will also run):
$ dmd -debug -offf find_files.d

Here is the output from a few test runs of the find_files utility:

Run with no arguments - shows usage:
$ ff
ff (Find Files) v0.1
Copyright 2016 Vasudev Ram - https://vasudevram.github.io
Usage: ff dir pattern
Recursively find filenames, under directory 'dir',
that match the literal or wildcard string 'pattern'.
Run with one argument, a non-existent directory - shows usage, since number of arguments is invalid:
$ ff z
ff (Find Files) v0.1
Copyright 2016 Vasudev Ram - https://vasudevram.github.io
Usage: ff dir pattern
Recursively find filenames, under directory 'dir',
that match the literal or wildcard string 'pattern'.
Run with two argument, a non-existent directory and a file wildcard, * - gives message that the directory does not exist, and shows usage:
$ ff z *
The name z does not exist or is not a directory.
ff (Find Files) v0.1
Copyright 2016 Vasudev Ram - https://vasudevram.github.io
Usage: ff dir pattern
Recursively find filenames, under directory 'dir',
that match the literal or wildcard string 'pattern'.
Run with two argument, an existing directory and a file wildcard, * - gives the output of the files matching the wildcard under that directory (recursively):
$ ff . *
.\dir1
.\dir1\a.txt
.\dir1\dir11
.\dir1\dir11\b.txt
.\dir2
.\dir2\c.txt
.\dir2\dir21
.\dir2\dir21\d.txt
.\ff.exe
.\ff.obj
.\ffd.exe
.\find_files.d
.\find_files.d~
Note: It will find hidden files too, i.e. those with a H attribute, as shown by the DOS command DIR /A. If you find any issue with the utility, please describe it, with the error message, in the comments.

You can get the find_files utility (as source code) from here on my Gumroad product store:

https://gum.co/find_files

Compile the find_files.d program with the Digital Mars D compiler using the command:

dmd find_files.d

whhich will create the executable file find_files.exe.

Run:

find_files

to get help on the usage of the utility. The examples above in this post have more details.

- Enjoy.

Drawing of magnifying glass at top of post, by:

Yours truly.

- Vasudev Ram - Online Python training and consulting

Get updates on my software products / ebooks / courses.

Jump to posts: Python   DLang   xtopdf

Subscribe to my blog by email

My ActiveState recipes

Managed WordPress Hosting by FlyWheel



Wednesday, October 5, 2016

Get names and types of a Python module's attributes


By Vasudev Ram



Hi readers,

Today I thought of this simple Python utility while using introspection to look at some modules.

It looks at a module, and for each attribute in it, it tells you the name and type of the attribute. This is useful if you are exploring some new Python module (built-in or third-party), and you want, for example, to know all the functions or methods in it, so that you can further introspect those by printing their docstrings, using the form:
print(module_name.function_or_method_name.__doc__)
because the docstring of a Python function of method, if present, is a nice capsule summary of: its arguments, what it does, and its return value (i.e. its input, processing and output). So with such a docstring, in many cases, a reasonably experienced programmer may not even need to look up the actual Python docs for that function or method, before beginning to use it, thereby saving their time.

So here is the utility:
from __future__ import print_function

# mod_attrs_and_types.py 
# Purpose: To show the attribute names and types 
# of a Python module, to help with learning about it.
# Author: Vasudev Ram
# Copyright 2016 Vasudev Ram
# Web site: https://vasudevram.github.io
# Blog: http://jugad2.blogspot.com
# Product store: https://gumroad.com/vasudevram

import sys

def attrs_and_types(mod_name):

    print('Attributes and their types for module {}:'.format(mod_name))
    print()
    for num, attr in enumerate(dir(eval(mod_name))):
        print("{idx}: {nam:30}  {typ}".format(
            idx=str(num + 1).rjust(4),
            nam=(mod_name + '.' + attr).ljust(30), 
            typ=type(eval(mod_name + '.' + attr))))

attrs_and_types(sys.__name__)
Running it like this:
$ python mod_attrs_and_types.py > out
gave this output:
Attributes and their types for module sys:

   1: sys.__displayhook__             <type 'builtin_function_or_method'>
   2: sys.__doc__                     <type 'str'>
   3: sys.__egginsert                 <type 'int'>
   4: sys.__excepthook__              <type 'builtin_function_or_method'>
   5: sys.__name__                    <type 'str'>
   6: sys.__package__                 <type 'NoneType'>
   7: sys.__plen                      <type 'int'>
   8: sys.__stderr__                  <type 'file'>
   9: sys.__stdin__                   <type 'file'>
  10: sys.__stdout__                  <type 'file'>
  11: sys._clear_type_cache           <type 'builtin_function_or_method'>
  12: sys._current_frames             <type 'builtin_function_or_method'>
  13: sys._getframe                   <type 'builtin_function_or_method'>
  14: sys._mercurial                  <type 'tuple'>
  15: sys.api_version                 <type 'int'>
  16: sys.argv                        <type 'list'>
  17: sys.builtin_module_names        <type 'tuple'>
  18: sys.byteorder                   <type 'str'>
  19: sys.call_tracing                <type 'builtin_function_or_method'>
  20: sys.callstats                   <type 'builtin_function_or_method'>
  21: sys.copyright                   <type 'str'>
  22: sys.displayhook                 <type 'builtin_function_or_method'>
  23: sys.dllhandle                   <type 'int'>
  24: sys.dont_write_bytecode         <type 'bool'>
  25: sys.exc_clear                   <type 'builtin_function_or_method'>
  26: sys.exc_info                    <type 'builtin_function_or_method'>
  27: sys.exc_type                    <type 'NoneType'>
  28: sys.excepthook                  <type 'builtin_function_or_method'>
  29: sys.exec_prefix                 <type 'str'>
  30: sys.executable                  <type 'str'>
  31: sys.exit                        <type 'builtin_function_or_method'>
  32: sys.flags                       <type 'sys.flags'>
  33: sys.float_info                  <type 'sys.float_info'>
  34: sys.float_repr_style            <type 'str'>
  35: sys.getcheckinterval            <type 'builtin_function_or_method'>
  36: sys.getdefaultencoding          <type 'builtin_function_or_method'>
  37: sys.getfilesystemencoding       <type 'builtin_function_or_method'>
  38: sys.getprofile                  <type 'builtin_function_or_method'>
  39: sys.getrecursionlimit           <type 'builtin_function_or_method'>
  40: sys.getrefcount                 <type 'builtin_function_or_method'>
  41: sys.getsizeof                   <type 'builtin_function_or_method'>
  42: sys.gettrace                    <type 'builtin_function_or_method'>
  43: sys.getwindowsversion           <type 'builtin_function_or_method'>
  44: sys.hexversion                  <type 'int'>
  45: sys.long_info                   <type 'sys.long_info'>
  46: sys.maxint                      <type 'int'>
  47: sys.maxsize                     <type 'int'>
  48: sys.maxunicode                  <type 'int'>
  49: sys.meta_path                   <type 'list'>
  50: sys.modules                     <type 'dict'>
  51: sys.path                        <type 'list'>
  52: sys.path_hooks                  <type 'list'>
  53: sys.path_importer_cache         <type 'dict'>
  54: sys.platform                    <type 'str'>
  55: sys.prefix                      <type 'str'>
  56: sys.py3kwarning                 <type 'bool'>
  57: sys.setcheckinterval            <type 'builtin_function_or_method'>
  58: sys.setprofile                  <type 'builtin_function_or_method'>
  59: sys.setrecursionlimit           <type 'builtin_function_or_method'>
  60: sys.settrace                    <type 'builtin_function_or_method'>
  61: sys.stderr                      <type 'file'>
  62: sys.stdin                       <type 'file'>
  63: sys.stdout                      <type 'file'>
  64: sys.subversion                  <type 'tuple'>
  65: sys.version                     <type 'str'>
  66: sys.version_info                <type 'sys.version_info'>
  67: sys.warnoptions                 <type 'list'>
  68: sys.winver                      <type 'str'>
There are other ways to do this, such as using the inspect module, but this is an easy way without inspect.

You can (e)grep for the pattern 'function|method' in the output, to get only the lines you want:

(If you haven't earlier, also check min_fgrep: minimal fgrep command in D.)
$ grep -E "function|method" out
1: sys.__displayhook__             <type 'builtin_function_or_method'>
   4: sys.__excepthook__              <type 'builtin_function_or_method'>
  11: sys._clear_type_cache           <type 'builtin_function_or_method'>
  12: sys._current_frames             <type 'builtin_function_or_method'>
  13: sys._getframe                   <type 'builtin_function_or_method'>
  19: sys.call_tracing                <type 'builtin_function_or_method'>
  20: sys.callstats                   <type 'builtin_function_or_method'>
  22: sys.displayhook                 <type 'builtin_function_or_method'>
  25: sys.exc_clear                   <type 'builtin_function_or_method'>
  26: sys.exc_info                    <type 'builtin_function_or_method'>
  28: sys.excepthook                  <type 'builtin_function_or_method'>
  31: sys.exit                        <type 'builtin_function_or_method'>
  35: sys.getcheckinterval            <type 'builtin_function_or_method'>
  36: sys.getdefaultencoding          <type 'builtin_function_or_method'>
  37: sys.getfilesystemencoding       <type 'builtin_function_or_method'>
  38: sys.getprofile                  <type 'builtin_function_or_method'>
  39: sys.getrecursionlimit           <type 'builtin_function_or_method'>
  40: sys.getrefcount                 <type 'builtin_function_or_method'>
  41: sys.getsizeof                   <type 'builtin_function_or_method'>
  42: sys.gettrace                    <type 'builtin_function_or_method'>
  43: sys.getwindowsversion           <type 'builtin_function_or_method'>
  57: sys.setcheckinterval            <type 'builtin_function_or_method'>
  58: sys.setprofile                  <type 'builtin_function_or_method'>
  59: sys.setrecursionlimit           <type 'builtin_function_or_method'>
  60: sys.settrace                    <type 'builtin_function_or_method'>
You can also (e)grep for a pattern or for alternative patterns:
$ grep -E "std(in|out)" out
   9: sys.__stdin__                   <type 'file'>
  10: sys.__stdout__                  <type 'file'>
  62: sys.stdin                       <type 'file'>
  63: sys.stdout                      <type 'file'>

The image at the top of the post is of a replica of a burning glass owned by Joseph Priestley, in his laboratory. If you don't remember your school physics, he is credited with having discovered oxygen.

- Enjoy.

- Vasudev Ram - Online Python training and consulting

Get updates on my software products / ebooks / courses.

Jump to posts: Python   DLang   xtopdf

Subscribe to my blog by email

My ActiveState recipes

Managed WordPress Hosting by FlyWheel



Thursday, September 22, 2016

num_cores: find number of cores in your PC's processor

By Vasudev Ram

Here is a simple D language utility, num_cores.d, which, when compiled (once) and run (any number of times), will show you the number of cores in the processor in your PC:
// num_cores.d
// A utility to show the number of cores in the processor in your PC.

import std.stdio;
import std.parallelism;

int num_cores() {
    return totalCPUs;
}

void main() {
    writeln("This computer's processor has ", num_cores, " core(s).");
}
The program uses the function totalCPUs from the D standard library module std.parallelism to get the number of cores.

To use it, download and install a D compiler such as DMD, the Digital Mars D compiler (or LDC or GDC). Use of DMD is shown here.

Then compile the program with:
dmd num_cores.d
Then run it:
num_cores
Output:
This computer's processor has 4 core(s).

- Vasudev Ram - Online Python training and consulting

Get updates on my software products / ebooks / courses.

Jump to posts: Python   DLang   xtopdf

Subscribe to my blog by email

My ActiveState recipes



Friday, September 2, 2016

Quick-and-dirty drive detector in Python (Windows)

By Vasudev Ram

While using Python's os.path module in a project, I got the idea of using it to do a quick-and-dirty check for what drives exist on a Windows system. Actually, not really the physical drives, but the drive letters, that may in reality be mapped any of the following: physical hard disk drives or logical partitions of them, CD or DVD drives, USB drives, or network-mapped drives.

The script, drives.py (below), has two functions, drives() and drives2(). The drives() function prints the required information. The drives2() function is more modular and hence more reusable, since it returns a list of detected drive letters; in fact, drives() can be implemented in terms of drives2().
from __future__ import print_function

'''
Author: Vasudev Ram
Copyright 2016 Vasudev Ram
Web site: https://vasudevram.github.io
Blog: http://jugad2.blogspot.com
Product store: http://gumroad.com/vasudevram
'''

from os.path import exists

def drives():
    # Limit of 'N' chosen arbitrarily.
    # For letters in the first half of the alphabet:
    for drive in range(ord('A'), ord('N')):
        print('Drive', chr(drive), 'exists:', exists(chr(drive) + ':'))

print()

drives()

print()

def drives2():
    drive_list = []
    for drive in range(ord('A'), ord('N')):
        if exists(chr(drive) + ':'):
            drive_list.append(chr(drive))
    return drive_list

print("The following drives exist:", drives2())
I ran it thusly:
$ python drives.py
And the output was thisly:
Drive A exists: False
Drive B exists: False
Drive C exists: True
Drive D exists: True
Drive E exists: True
Drive F exists: False
Drive G exists: False
Drive H exists: True
Drive I exists: False
Drive J exists: False
Drive K exists: False
Drive L exists: False
Drive M exists: False

The following drives exist: ['C', 'D', 'E', 'H']

As we can see, the program relies on the fact that a drive specification like "C:" is considered as a path on Windows, since it means "the current directory on drive C". That is why os.path.exists() works for this use. The program does not use a real OS API that returns information about available drives.

I have only tested it a few times, on my machine. It could be that in other tests, or on other machines, it may fail for some reason, such as a drive that is present but inaccessible for some reason (permissions, hardware issue or other). If you try it and get any errors, I'd be interested to know the details - please leave a comment. Thanks.

- Vasudev Ram - Online Python training and consulting

Get updates on my software products / ebooks / courses.

Jump to posts: Python   DLang   xtopdf

Subscribe to my blog by email

My ActiveState recipes



Sunday, July 31, 2016

deltildefiles: D language utility to recursively delete vim backup files

By Vasudev Ram

~

Here's a small utility I wrote in D (the D programming language). The utility is called deltildefiles (for "delete tilde files"). It lets you delete all files whose names end in "~", the tilde character (Wikipedia), under a specified directory, recursively, i.e. including such files found in sub-directories.

[ BTW, check out the Wikipedia article about tilde, linked above. It has many interesting uses in various domains, not just computer programming, for example, in physics, mathematics, economics, electronics and even juggling :) ]

The vim editor (if the option :se backup is set) names its backups of the files you edit, with the same file name as the original file, plus a tilde at the end. Of course, you can do the same task as this utility deltildefiles, with just a batch file (or two) which uses DEL (with or without /S) on Windows), so I just wrote this for fun and learning. However, if you want to enhance the task with other conditions, etc., then a program (or at least a script, in Python, Perl or other language) may be the better way to go, rather than writing an awkward batch file (even if that is possible) or using PowerShell (haven't used the latter). Another alternative is to use a shell script on Linux, or if you use Cygwin or other Unix emulation on Windows, to use the find and rm commands, that come with it, like:

$ find $dirName -print -name '*~' -exec rm {} \; # or some variation

Be careful with the above command. If you make a typing mistake, like omitting the ~, it could end up deleting the wrong files, and potentially many of them. This is also one reason to make the command into a binary (like I have done) or a shell script, test it thoroughly with dummy / safe data, and from then onward, only use that, instead of typing the find command each time - at least for commands that can delete data or cause other damage.

Anyway, here is the code for deltildefiles.d:
/****************************************************************
File: deltildefiles.d
Purpose: To delete vim backup files, i.e. files ending with ~.
Compile with:
$ dmd deltildefiles.d

Author: Vasudev Ram
Copyright 2016 Vasudev Ram
Web site: https://vasudevram.github.io
Products: https://gumroad.com/vasudevram

Description: To delete all files whose names end with 
the tilde character (~) in the directory subtree 
specified as the command-line argument. 

When you edit a file abc.txt with the vim editor, it will 
first make a backup in the file abc.txt~ (note ~ character
at end of file name). Over time, these files can accumulate.
This utility helps you to delete all such vim backup files 
in a specified directory and its subdirectories.

Use with caution and at your own risk!!!
On most operating systems, once a file is deleted this way
(versus sending to the Recycle Bin on Windows), it is not 
recoverable, unless you have installed some undelete utility.
****************************************************************/

import std.stdio;
import std.file;

void usage(string[] args) {
    stderr.writeln("Usage: ", args[0], " dirName");
    stderr.writeln(
        "Recursively delete files whose names end with ~ under dirName.");
}

int main(string[] args) {
    if (args.length != 2) {
        usage(args);
        return 1;
    }
    string dirName = args[1];
    // Check if dirName exists.
    if (!exists(dirName)) {
        stderr.writeln("Error: ", dirName, " not found. Exiting.");
        return 1;
    }
    // Check if dirName is not the NUL device and is actually a directory.
    if (dirName == "NUL" || !DirEntry(dirName).isDir()) {
        stderr.writeln("Error: ", dirName, " is not a directory. Exiting.");
        return 1;
    }
    try {
        foreach(DirEntry de; dirEntries(args[1], "*~", SpanMode.breadth)) {
            // The isFile() check may be enough, also need to check for
            // Windows vs POSIX behavior.
            if (de.isFile() && !de.isDir()) {
                writeln("Deleting ", de.name());
                remove(de.name());
            }
        }
    } catch (FileException) {
        stderr.writeln("Caught a FileException. Exiting.");
        return 1;
    } catch (Exception) {
        stderr.writeln("Caught an Exception. Exiting.");
        return 1;
    }
    return 0;
}
Compile it with:
$ dmd deltildefiles.d
And you can run it like this:
$ deltildefiles .
which will delete all files ending in ~, in and under the current directory. If you give a file name instead of a directory name, or if you give a non-existent directory name, it gives an error message and exits.

It seems to work as of now, based on some testing I did. May have a few bugs since I haven't tested it exhaustively. May make a few improvements to it over time, such as generalizing from ~ to filename wildcards, more error handling, verbose / quiet flags, etc.

Translate this post into another language with Google Translate
(and, just for kicks, click the speaker icon below the right hand side text box at the above Translate page :).

- Vasudev Ram - Online Python training and consulting

Follow me on Gumroad to get email updates about my products.


My Python posts     Subscribe to my blog by email

My ActiveState recipes



Thursday, April 7, 2016

bsplit - binary file split utility in Python

By Vasudev Ram

Some days ago I had written a post about a Unix-like file split utility that I wrote in Python:

Unix split command in Python

I mentioned that unlike the Unix split, I had written mine to only work on text files, because it might be preferable to do it that way (the "do one thing well" idea). I had also said I could write the binary file split as a separate tool. Here it is - bsplit.py:

import sys

import os OUTFIL_PREFIX = "out_" def error_exit(message, code=1): sys.stderr.write("Error:\n{}".format(str(message))) sys.exit(code) def err_write(message): sys.stderr.write(message) def make_out_filename(prefix, idx): '''Make a filename with a serial number suffix.''' return prefix + str(idx).zfill(4) def bsplit(in_filename, bytes_per_file): '''Split the input file in_filename into output files of bytes_per_file bytes each. Last file may have less bytes.''' in_fil = open(in_filename, "rb") outfil_idx = 1 out_filename = make_out_filename(OUTFIL_PREFIX, outfil_idx) out_fil = open(out_filename, "wb") byte_count = tot_byte_count = file_count = 0 c = in_fil.read(1) # Loop over the input and split it into multiple files # of bytes_per_file bytes each (except possibly for the # last file, which may have less bytes. while c != '': byte_count += 1 out_fil.write(c) # Bump vars; change to next output file. if byte_count >= bytes_per_file: tot_byte_count += byte_count byte_count = 0 file_count += 1 out_fil.close() outfil_idx += 1 out_filename = make_out_filename(OUTFIL_PREFIX, outfil_idx) out_fil = open(out_filename, "wb") c = in_fil.read(1) # Clean up. in_fil.close() if not out_fil.closed: out_fil.close() if byte_count == 0: os.remove(out_filename) def usage(): err_write( "Usage: [ python ] {} in_filename bytes_per_file\n".format( sys.argv[0])) err_write( "splits in_filename into files with bytes_per_file bytes\n".format( sys.argv[0])) def main(): if len(sys.argv) != 3: usage() sys.exit(1) try: # Do some checks on arguments. in_filename = sys.argv[1] if not os.path.exists(in_filename): error_exit( "Input file '{}' not found.\n".format(in_filename)) if os.path.getsize(in_filename) == 0: error_exit( "Input file '{}' has no data.\n".format(in_filename)) bytes_per_file = int(sys.argv[2]) if bytes_per_file <= 0: error_exit( "bytes_per_file cannot be less than or equal to 0.\n") # If all checks pass, split the file. bsplit(in_filename, bytes_per_file) except ValueError as ve: error_exit(str(ve)) except IOError as ioe: error_exit(str(ioe)) except Exception as e: error_exit(str(e)) if __name__ == '__main__': main()

The program takes two command line arguments: - the name of an input file to split - the number of bytes per file, into which to split the input file

I tested bsplit with various combinations of test input files and bytes_per_file values. It worked as expected. But if you find any issues, I'd be interested to know - please leave a comment.

Some other recent posts related to the split / bsplit utilities:

A basic file compare utility in Python

Python one-liner to compare two files (conditions apply)

- Enjoy.

- Vasudev Ram - Online Python training and programming

Signup to hear about new products and services I create.

Posts about Python  Posts about xtopdf

My ActiveState recipes

Saturday, March 26, 2016

A basic file compare utility in Python

By Vasudev Ram


Weighing dishes from the island of Thera, Minoan civilization, 2000–1500 BC

Image attribution: Norbert Nagel

Recently, I had written a simple version of the Unix split command in Python. In order to check whether a split command works correctly, you have to join the files it creates - the split files - back into a single file, and then compare that new file to the original input file. So you need a file comparison utility. While both Unix and Windows have such utilities (cmp and fc.exe respectively), I thought of writing a simple one in Python. I did that, and then tested it with a few pairs of input files.

Here is the code, in file_compare.py:
# file_compare.py
# A simple file comparison utility.
# Author: Vasudev Ram
# Copyright 2016 Vasudev Ram

import sys
import os
from os.path import exists, getsize

def out_write(msg):
    sys.stdout.write(msg)

def err_write(msg):
    sys.stderr.write(msg)

def usage():
    err_write("Usage: {} file_a file_b\n".format(sys.argv[0]))

def file_object_compare(in_fil_a, in_fil_b):
    '''Logic: Assume files are equal to start with.
    Read both files, character by character.
    Compare characters at corresponding byte offsets. 
    If any pair at the same offset don't match, the files 
    are unequal. If we reach the end of the files, and 
    there was no mismatch, the files are equal.  We do not
    check for one file being a strict subset of the other, 
    because we only enter this function if the files are 
    of the same size.'''

    files_are_equal = True
    pos = 0
    while True:
        ca = in_fil_a.read(1)
        if ca == '':
            break
        cb = in_fil_b.read(1)
        if cb == '':
            break
        if ca != cb:
            files_are_equal = False
            break
        pos += 1
        if pos % 10000 == 0:
            print pos, 

    if files_are_equal:
        return (True, None)
    else:
        return (False, "files differ at byte offset {}".format(pos))

def file_compare(in_filename_a, in_filename_b):
    '''Compare the files in_filename_a and in_filename_b.
    If their contents are the same, return (True, None).
    else return (False, "[reason]"), where [reason] 
    is the reason why they are different, as a string.
    Reasons could be: file sizes differ or file contents differ.'''

    if getsize(in_filename_a) != getsize(in_filename_b):
        return (False, "file sizes differ")
    else:
        in_fil_a = open(in_filename_a, "rb")
        in_fil_b = open(in_filename_b, "rb")
        result = file_object_compare(in_fil_a, in_fil_b)
        in_fil_a.close()
        in_fil_b.close()
        return result
        
def main():
    if len(sys.argv) != 3:
        usage()
        sys.exit(1)

    try:
        # Get the input filenames.
        in_filename_a, in_filename_b = sys.argv[1:3]
        # Check they exist.
        for in_filename in (in_filename_a, in_filename_b):
            if not exists(in_filename):
                err_write(
                    "Error: Input file '{}' not found.\n".format(in_filename))
                sys.exit(1)
        # Don't allow comparing a file with itself.
        if in_filename_a == in_filename_b:
            out_write("No sense comparing {} against itself.".format(in_filename_a))
            sys.exit(0)
        # Compare the files.
        result = file_compare(in_filename_a, in_filename_b)
        if result[0]:
            out_write("Files compare equal.")
        else:
            out_write("Files compare unequal: {}".format(result[1]))
        sys.exit(0)
    except IOError as ioe:
        sys.stderr.write("Caught IOError: {}\n".format(str(ioe)))
    except Exception as e:
        sys.stderr.write("Caught Exception: {}\n".format(str(e)))

if __name__ == '__main__':
    main()
And here are a few input files I ran it with (containing differences at progressive character positions), a few runs of the program, and the output of those runs:
$ type f0.txt
file 1

$ type f1.txt
file 1

$ type f2.txt
file 2

$ type f3.txt
file 3

$ type f4.txt
mile 1

$ type f5.txt
fale 1

$ type f6.txt
fire 1

$ python file_compare.py
Usage: file_compare.py file_a file_b

$ python file_compare.py a b
Error: Input file 'a' not found.

$ python file_compare.py f0.txt f1.txt
Files compare equal.

$ python file_compare.py f0.txt f2.txt
Files compare unequal: files differ at byte offset 5

$ python file_compare.py f1.txt f2.txt
Files compare unequal: files differ at byte offset 5

$ python file_compare.py f2.txt f2.txt
No sense comparing f2.txt against itself.

$ python file_compare.py f1.txt f3.txt
Files compare unequal: files differ at byte offset 5

$ python file_compare.py f1.txt f4.txt
Files compare unequal: files differ at byte offset 0

$ python file_compare.py f1.txt f5.txt
Files compare unequal: files differ at byte offset 1

$ python file_compare.py f1.txt f6.txt
Files compare unequal: files differ at byte offset 2

$ python file_compare.py f1.txt f7.txt
Error: Input file 'f7.txt' not found.

$ python file_compare.py f64MB f64MB2
Files compare equal.
Most of the files tested were small, but I also tested with some files of tens of lines, and the last pair of files tested was 64 MB each.

Note:

These two lines:
if pos % 10000 == 0:
            print pos, 
are present in order to display a progress counter, for comparisons on large files. You can delete them if you don't want to monitor the progress of the comparison.

Currently I am using read(1), which means Python is reading the file character by character. There are potentially many levels of buffering that happen anyway, such as at the level of the C stdio library that underlies CPython's I/O, the OS, the hard disk controller, and even the CPU. But it may be possible to improve the performance of this program, by specifying some buffer when opening the files.

See:

Python open function
and
Default buffer size for a file

It's possible to write a much shorter version of this program, subject to certain limitations :-) Can you guess how? If you have an idea, mention it in the comments.

The image at the top is of weighing dishes from the island of Thera, Minoan civilization, 2000–1500 BC.

- Enjoy.

- Vasudev Ram - Online Python training and programming

Signup to hear about new products and services I create.

Posts about Python  Posts about xtopdf

My ActiveState recipes

Tuesday, March 15, 2016

Unix split command in Python

By Vasudev Ram

Recently, there was an HN thread about the implementation (not just use) of text editors. Someone mentioned that some editors, including vim, have problems opening large files. Various people gave workarounds or solutions, including using vim and other ways.

I commented that you can use the Unix command bfs (for big file scanner), if you have it on your system, to open the file read-only and then move around in it, like you can in an editor.

I also said that the Unix commands split and csplit can be used to split a large file into smaller chunks, edit the chunks as needed, and then combine the chunks back into a single file using the cat commmand.

This made me think of writing, just for fun, a simple version [1] of the split command in Python. So I did that, and then tested it some [2]. Seems to be working okay so far.

[1] I have not implemented the full functionality of the POSIX split command, only a subset, for now. May enhance it with a few command-line options, or more functionality, later, e.g. with the ability to split binary files. I've also not implemented the default size of 1000 lines, or the ability to take input from standard input if no filename is specfied. (Both are easy.)

However, I am not sure whether the binary file splitting feature should be a part of split, or should be a separate command, considering the Unix philosophy of doing one thing and doing it well. Binary file splitting seems like it should be a separate task from text file splitting. Maybe it is a matter of opinion.

[2] I tested split.py with various valid and invalid values for the lines_per_file argument (such as -3, -2, -1, 0, 1, 2, 3, 10, 50, 100) on each of these input files:

in_file_0_lines.txt
in_file_1_line.txt
in_file_2_lines.txt
in_file_3_lines.txt
in_file_10_lines.txt
in_file_100_lines.txt

where the meaning of the filenames should be self-explanatory.

Of course, I also checked after each test run, that the output file(s) contained the right data.

(There may still be some bugs, of course. If you find any, I'd appreciate hearing about it.)

Here is the code for split.py:

import sys
import os

OUTFIL_PREFIX = "out_"

def make_out_filename(prefix, idx):
    '''Make a filename with a serial number suffix.'''
    return prefix + str(idx).zfill(4)

def split(in_filename, lines_per_file):
    '''Split the input file in_filename into output files of 
    lines_per_file lines each. Last file may have less lines.'''
    in_fil = open(in_filename, "r")
    outfil_idx = 1
    out_filename = make_out_filename(OUTFIL_PREFIX, outfil_idx)
    out_fil = open(out_filename, "w")
    # Using chain assignment feature of Python.
    line_count = tot_line_count = file_count = 0
    # Loop over the input and split it into multiple files.
    # A text file is an iterable sequence, from Python 2.2,
    # so the for line below works.
    for lin in in_fil:
        # Bump vars; change to next output file.
        if line_count >= lines_per_file:
            tot_line_count += line_count
            line_count = 0
            file_count += 1
            out_fil.close()
            outfil_idx += 1
            out_filename = make_out_filename(OUTFIL_PREFIX, outfil_idx)
            out_fil = open(out_filename, "w")
        line_count += 1
        out_fil.write(lin)
    in_fil.close()
    out_fil.close()
    sys.stderr.write("Output is in file(s) with prefix {}\n".format(OUTFIL_PREFIX))
        
def usage():
    sys.stderr.write(
    "Usage: {} in_filename lines_per_file\n".format(sys.argv[0]))

def main():

    if len(sys.argv) != 3:
        usage()
        sys.exit(1)

    try:
        # Get and validate in_filename.
        in_filename = sys.argv[1]
        # If input file does not exist, exit.
        if not os.path.exists(in_filename):
            sys.stderr.write("Error: Input file '{}' not found.\n".format(in_filename))
            sys.exit(1)
        # If input is empty, exit.
        if os.path.getsize(in_filename) == 0:
            sys.stderr.write("Error: Input file '{}' has no data.\n".format(in_filename))
            sys.exit(1)
        # Get and validate lines_per_file.
        lines_per_file = int(sys.argv[2])
        if lines_per_file <= 0:
            sys.stderr.write("Error: lines_per_file cannot be less than or equal to 0.\n")
            sys.exit(1)
        # If all checks pass, split the file.
        split(in_filename, lines_per_file) 
    except ValueError as ve:
        sys.stderr.write("Caught ValueError: {}\n".format(repr(ve)))
    except IOError as ioe:
        sys.stderr.write("Caught IOError: {}\n".format(repr(ioe)))
    except Exception as e:
        sys.stderr.write("Caught Exception: {}\n".format(repr(e)))
        raise

if __name__ == '__main__':
    main()
You can run split.py like this:
$ python split.py
Usage: split.py in_filename lines_per_file
which will give you the usage help. And like this to actually split text files, in this case, a 100-line text file into 10 files of 10 lines each:
$ python split.py in_file_100_lines.txt 10
Output is in file(s) with prefix out_
Here are a couple of runs with invalid values for either the input file or the lines_per_file argument:
$ python split.py in_file_100_lines.txt 0
Error: lines_per_file cannot be less than or equal to 0.

$ python split.py not-there.txt 0
Error: Input file 'not-there.txt' not found.
As an aside, thinking about whether to use 0 or 1 as initial value for some of the _count variables in the program, made me remember this topic:

Why programmers count from 0

See the first few hits for some good answers.

And finally, speaking of zero, check out this earlier post by me:

Bhaskaracharya and the man who found zero

- Enjoy.

- Vasudev Ram - Online Python training and programming

Signup to hear about new products and services I create.

Posts about Python  Posts about xtopdf

My ActiveState recipes

Friday, May 8, 2015

tabtospaces, utility to change tabs to spaces in Python files

By Vasudev Ram




Near the end of a recent blog post:

asciiflow.com: Draw flowcharts online, in ASCII

, I showed how this small snippet of Python code can be used to make a Python program usable as a component in a Unix pipeline:
for lin in sys.stdin:
    sys.stdout.write(process(lin))


Today I saw Raymond Hettinger (@raymondh)'s tweet about the -t and -tt command line options of Python:
#python tip: In Python 2, the -tt option raises an error when you foolishly mix spaces and tabs. In Python 3, that is always an error.
That made me think of writing a simple Python 2 tool to change the tabs in a Python file to spaces. Yes, I know it can be easily done in Unix or Windix [1] with any of sed / awk / tr etc. That's not the point. So here is tabtospaces.py:
import sys
for lin in sys.stdin:
    sys.stdout.write(lin.replace("\t", "    "))
[ Note: this code converts each tab into 4 spaces. It can be parameterized by passing a command-line option that specifies the number of spaces, such as 4 or 8, and then replacing each tab with that many spaces. Also note that I have not tested the program on many sets of data, just one for now. ]

I created a simple Python file, test1.py, that has mixed tabs and spaces to use as input to tabtospaces.py. Then I ran the following commands:
$ py -tt test1.py
  File "test1.py", line 4
    print arg,
              ^
TabError: inconsistent use of tabs and spaces in indentation

$ py tabtospaces.py < test1.py > test2.py

$ py -tt test2.py
0 1 2 3 4 5 6 7 8 9
which shows that tabtospaces.py does convert the tabs to spaces.

And you can see from this diff that the original test1.py and the test2.py generated by tabtospaces.py, differ only in the use of tabs vs. spaces:
$ fc /l test1.py test2.py
Comparing files test1.py and TEST2.PY
***** test1.py
    for arg in args:
                print arg,

***** TEST2.PY
    for arg in args:
        print arg,

*****

[1] Windix is the latest upcoming Unix-compatible OS from M$, due Real Soon Now. You heard it here first - TM.

- Vasudev Ram - Online Python training and programming

Dancing Bison Enterprises

Signup to hear about new software products or info-products that I create.

Posts about Python  Posts about xtopdf

Contact Page

Thursday, November 21, 2013

Winamp shutting down 20 Dec 2013


By Vasudev Ram



Winamp will be shutting down on 20 December 2013, according to this post I just saw on Hacker News.

Winamp on Wikipedia

As someone said in the HN thread, "the end of an era". I used to enjoy fiddling around with different Winamp skins, apart from using it as a music player.

The HN thread linked above has a link to an interesting article on Ars Technica about WinAmp's history.

According to the notice on the Winamp site (near the top of the page), Winamp downloads will not be available after the site shuts down. So go grab your copy of Winamp before it's too late.

Here is Bob Marley playing Trenchtown Rock (you can skip any YouTube ad that may appear, after a few seconds):



- Vasudev Ram - Dancing Bison Enterprises

Saturday, November 9, 2013

A digital clock for Windows

By Vasudev Ram

In my recent post, A simple alarm clock in Python, I mentioned that I had once created a digital clock in Delphi.

Here is a screenshot of another digital clock that I created today; this one includes the date as well as the time:




(The image above is of Pythia, the Delphic oracle.)

- Vasudev Ram - Dancing Bison Enterprises

Consulting / training inquiry

O'Reilly 50% Ebook Deal of the Day

Saturday, November 24, 2012

pinger utilities have multiple uses

Python | Host/Device Ping Utility for Windows

Saw the above pinger utility written by Corey Goldberg a while ago. It is in Python and is multi-threaded.

Seeing it reminded me of writing a pinger utility some years ago for a company I worked for at the time; it was for Unix systems, and was not multi-threaded.

It was written in a combination of Perl (for regex usage), shell and C.

The C part (a program that was called from the controlling shell script) was used to overcome an interesting issue: a kind of "drift" in the times at which the ping command would get invoked.

The users wanted it to run exactly on the minute, every n minutes, but it would sometimes run a few seconds later.

I used custom C code to solve the issue.

Later I learned (by reading more docs :) that the issue could probably have been solved by calling a Unix system call or two (like gettimeofday or getitimer, I forget exactly which right now) from my C program.

Anyway, the tool ended up being used to monitor the uptime of many Unix servers at the company. The sysadmins (who had asked me to create the tool) said that it was useful.

As Corey says in his post, pinger tools can be used to monitor network latency, check if hosts / devices are alive, and also to log and report on their uptime over an extended period, for reporting and for taking corrective action (as my utility was used).

Also check out pingdom.com for an example of a business built on these concepts. Site24x7.com is another such business; it is part of the same company as Zoho.com. They were (and still are)  into network monitoring / management before they created the Zoho suite of web apps.

I use both Pingdom and Site24x7 on my business web site www.dancingbison.com, from over a year or more now, to monitor its uptime, and both are fairly good at that.

Friday, November 9, 2012

Gow - Gnu on Windows, a lighter Cygwin

Home · bmatzelle/gow Wiki · GitHub

The author says it is quite a bit smaller than Cygwin. It has over a 100 commonly used / useful command line Unix utilities ported to Windows.

Blogged in a bus via Blogger Android app.
Vasudev Ram
www.dancingbison.com

Saturday, July 30, 2011

Check out RocketDock and Dexpot, for Windows

By Vasudev Ram - dancingbison.com | @vasudevram | jugad2.blogspot.com

Just read about them today.

Rocketdock - (http://rocketdock.com) is an application launcher, and Dexpot - (http://dexpot.de) is for multiple virtual desktops; both are for Windows. Haven't tried them out yet myself, just downloaded them (okay, I tried Dexpot, but only a little), but they might be good. As with any software that you're trying out for the first time, of course, watch out for any issues. Back up your important data and software first.

Posted via email
- Vasudev Ram - Dancing Bison Enterprises