Hiển thị các bài đăng có nhãn Windows-utilities. Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn Windows-utilities. Hiển thị tất cả bài đăng

Thứ Bảy, 8 tháng 4, 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



Thứ Sáu, 10 tháng 2, 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



Thứ Bảy, 7 tháng 1, 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



Thứ Bảy, 12 tháng 11, 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



Thứ Năm, 13 tháng 10, 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



Thứ Ba, 4 tháng 10, 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



Thứ Tư, 21 tháng 9, 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



Thứ Năm, 1 tháng 9, 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



Thứ Bảy, 30 tháng 7, 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