Latest Release: 

dm is an ls-like lister for CBM container formats - that includes both physical-media image formats (like .d64, .t64 .p00) and native/archival formats (like .lnx and [1-4]! zips). dm also includes a growing number of useful sub-commands for performing various tasks on supported containers formats that make sense in the command line context. Think of dm as a command line 'cousin' to DirMaster. dm was originally called cbmls when its only feature was listing.

With the release of v1.4.0 there are five sub-commands; the default when no command is explicitly selected is 'ls' and in general dm will behave exactly like cbmls did. But you can also use 'dm ls' if you want to explicitly invoke the ls/listing feature. i.e. the following are equivalent:

dm ls -lc disk.d64
dm -lc disk.d64      # sub-command omitted

Currently, these sub-commands are available: 'ls', 'diff', 'zip' ,'unzip', and 'grep'.

As always we invite bug reports and feature requests; those should be directed here.

'dm ls'

If you know what 'ls' is you'll find comfort with some of the command line options (try 'dm --help')

'dm ls' - Features

  • recursively process file system subdirectories

  • recursively process *within* disk images and file containers

  • support for input/output redirection

  • choice of output: canonical "$" style or columns
  • control over column output/order
  • sensible output for cp437 or Unicode
  • use with our font, C64 Pro Mono, for a genuine PETSCII shell experience

'dm ls' - Screenshots:

dm will present as good an output as possible in a default cmd shell... some PETSCII characters map sensibly and color is an option.

cmd on Windows XP

and with colorized output...

It's a little smoother if you switch to a TrueType font. But some TrueType fonts, like the Lucida Console used below, don't have all the applicable characters that we can map to from PETSCII and show filler as seen in the middle...  other TrueType fonts have a fuller set of glyphs like PragmataPro on the right.

Windows 8.1 with Lucida font

Lucida is missing some glyphs...

but PragmataPro has them!

Of course the best way for hardcore c64 freaks to look at their directories is made possible with our C64 Pro Mono font:

Windows 7 and the majesty of load"$",8

dm works similarly on Linux and macOS:

Mate Terminal on Mint

iTerm2 on Mac OS X 10.7

'dm ls' - General use:

dm will try to process all 'loose' arguments on the command line as a potential disk/archive image or directory. Order or mixture with command options does not matter. There is also some support for reading disk/archive data from a pipe or redirection. Default behavior is to list directories in the 'canonical' load"$" format. A column-based listing is also available, and you have full control of column selection and ordering. The following shows the 'long listing' (-l or --long) output which is a short cut for outputting every column: blocks, bytes, index, track/sector, load address, name, splat, type and lock (there are no splatted/locked files on this directory):

output from 'dm -lc happy--style.d64'

Recursion, or directory traversal if you prefer, is possible in two axes: recursion through the os file system and recursion through disk/archive contents. The latter is referred to in the program as a deep listing and when selected dm will show you the contents of archives, subdirectories and partitions, as deep as possible (e.g. an arc inside a lnx inside a zip-4 inside a 1581 subdir).

'dm ls' - Recipes:

List the contents of oldstuff.lbr and disk.d64 using the long column output, with color.

dm oldstuff.lbr -lc disk.d64

Pipe an uncompressed disk image into dm for listing, using the lower/upper character mode instead of the default upper/graphics:

xz -d mule.d64.xz | dm -C lower

List the contents of every recognized disk image and container starting with the current working directory (all files and recursing into all subdirectories):

dm -lR .

Deep list the contents of the .d4m image using color, outputting three columns in the given order - this will include the contents of all partitions and any archiver containers discovered therein:

dm -dc disk.d4m --columns bytes,name,index

Note that the argument for '--columns' must be a comma-separated list, with no spaces! 'dm --help' will show you the possible valid column names.

'dm diff'

'dm diff' will compare two block-based disk images (e.g. a .d81 is block-based, while a .t64 is not) at a byte-by-byte level and report on differences. You can use 'dm diff --help' for a list of options to this command.

'dm diff' - Features

  • brief or detailed (-v) output

  • optional BAM visualization display

  • also reports on differences in error codes, if any

'dm diff' - Recipes:

Show a detailed summary of the differences between a d64 and a g64 (note that the g64 is interpreted as if it were converted to a d64 first!).

dm diff disk.d64 disk.g64 -v

Show the differences between the two disk images using a BAM visualization in addition to a brief summary; also include a legend explaining the BAM symbols:

dm diff disk1.d64 disk2.d64 --bam --legend


'dm grep'

'dm grep' searches block-based CBM containers (like d64, d81) for a byte pattern taking into account the container's internal block/link based geometry. For now, the byte pattern is a fixed sequence of bytes (ergo, this works more like 'fgrep' or 'grep -F' although wildcards and/or regular expressions would eventually be added).

'dm grep' - search patterns:

A byte sequence pattern can be expressed as a serialized hex string, as implicit PETSCII, or as explicit ASCII.

By "serialized hex" we mean simply an ASCII representation of bytes encoded as hexadecimal values. dm is very flexible in what actual text representations it can accept; all non-hexadecimal characters are ignored or used as delimiters. The first character of the pattern must be the dollar sign, '$'. After that, hexadecimal values are read in pairs, or if delimited as single digits. Here are some examples of valid serialized hex strings which are all interpreted as three bytes, values 1, 2 and 3:

"$010203"    "$01 02 03"    "$01, $02, $03"    "$1 2 3"    "$01:02:03"  "$01x02y03z!"

The goal here is compatibility with the variety of formats that sequences of hex bytes appear in software - hex editors, and other tools, for ease of use when copy-pasting strings. Of course the final example above is contrived just to illustrate the earlier point - all non hexadecimal characters act as delimiters or are ignored. Note that some command shells will treat '$' as a special character that invokes some shell feature. Depending on the shell, you may be able to escape the '$' with, e.g., a '\' or some other character. As a final resort, the cli option "-h/--pattern-hex" can be used to force dm to interpret the pattern as hex even if it doesn't start with '$'.

By "implicit PETSCII" we mean PETSCII which is implied from interpreting an ASCII representation as though the current CBM case mode is lower/upper. For example:

dm grep "abc" disk.d64  # pattern evaluates to $414243
dm grep "ABC" disk.d64  # pattern evaluates to $c1c2c3

By "explicit ASCII" we mean the pattern is taken literally as an ASCII string, which in the context of CBM containers can be useful for searching GEOS related media.

In addition to "-h/--pattern-hex" to declare a serialized hex pattern, you can use "-p/--pattern-petscii" and "-a/--pattern-ascii" to declare that a pattern should be interpreted as PETSCII or ASCII. The default when none of the three pattern declaration options is provided is to check for a leading '$' and interpret as serialized hex if found, or as PETSCII otherwise.

There is nothing inherent in dm that necessitates using quotes around your pattern - space characters in your pattern would obviously require quotes. Depending on the pattern and your command shell, you may need to use quotes when using certain other characters including '$' as already noted above.

'dm grep' - output:

The output format when matches are found mimics output from the unix grep command. Here are some example results from searching a disk image:

> dm grep abc disk.d64

> dm grep "$313233" -b dsk_*.d64 disk.d64

Output format consists of the filename of the OS-native file where a match was located, followed by the track,sector of the match. When a partial match is found at the end of a sector, which is then completed by following a valid chain to the next linked sector, dm will output the match as a pair of track,sector notations as shown in the second match in the first example above (the match spans track 2, sector 2 and track 2, sector 3). 

When using the cli option "-b/--byte-offset', the byte offset of the start of the match is included in output. The second set of results shows where the offset is displayed, either after the track,sector notation, or after the first track,sector and before the second.

Several other cli options are available to control output and which are similar to and influenced by unix grep; you can see all options with

dm grep --help