snag - command to reserve a previously unused file or directory version


snag [-f] name[/] ...
snag [-f] [--lshigh | --lslow | --mknext | --mknextcopy] name[/] ...


The snag command provides a robust way to "capture without clobbering" a specified filesystem node name or a version of that name. The first form of the command (not version-aware) creates a previously non-existing filesystem node, name. If name ends with a '/' character, the node is taken to be a directory, otherwise it is taken to be a file. It outputs the created node name on success and exits with status 0. Other errors result in exit status 2 and a message on stderr.

Unlike the touch(1) command, snag is guaranteed to fail if the node exists already (exit status 1). Because it attempts to create the node first and tests for existence afterwards, it is not susceptible to the race condition that arises when these steps are reversed. There is an exception when -f (--force) is given, in which case an attempt will be made first to remove a pre-existing node; caution should be exercised as a race condition makes it possible to succeed in removing a node but to fail in re-capturing it.

Versions are only relevant for the second form of the snag command, where "version" has no other meaning than a filesytem node name that may end in a string of digits. The node name is considered a base for numbered version names and any terminal digits in name ("1" by default if there are no terminal digits) are interpreted specially. The length of the terminal digit string determines the minimum width of the version number, zero-padded if necessary, and the value of the digit string is the first version number to use if no numbered versions exist.

This second form of the command provides a safe and efficient way to capture an unused version. If a race condition is detected, it will make several attempts to capture a higher unused version before giving up.

If --lshigh ("list high") is given, no node will be created, but the highest existing numbered version will be returned, where candidate versions will be any node name beginning with the base name and ending in any string of digits. Similarly for --lslow ("list low"), but for the lowest existing numbered version.

If --mknext is given, an attempt will be made to create the next highest numbered version by adding one to the current highest version number. If a race condition is detected, several attempts will be made. The next highest version is determined by first finding the highest current version number and adding 1 to it. It is an error if the type (file or directory) of the requested version is different from that of the current high version unless --force is given.

Where files are concerned, the --mknextcopy option behaves like --mknext but with the new file receiving a copy of the unnumbered file. It is an error in this case if the specified node does not exist already as an unnumbered file.


  $ snag myfile                # create an empty file
  $ snag myfile                # fails if it exists
  myfile already exists
  $ cp ~/protostuff myfile     # get new content into myfile
  $ snag --mknextcopy myfile   # copy original as version 1
  $ vi myfile                  # make changes to your original
  $ snag --mknextcopy myfile   # save changes as version 2
  $ vi myfile                  # continue making changes

  $ snag v4/                   # create a numbered directory
  $ snag --mknext v001/        # next is 5, but "001" pads to 005
  $ snag --mknext v001/        # "001" is first version if none
  $ snag --mknext v001/        # but is ignored if versions exist
  $ rmdir v006                 # leaving a hole in the series
  $ snag -mknext v005/         # doesn't effect next highest
  $ snag v999/                 # leave a big gap and show that
  $ snag -mknext v005/         # "005" is only a minimum width


-f, --force

Force the overwrite of an existing node or the creation of a next version of a different type from that of the current highest version.

-h, --help

Print extended help documentation.

--lshigh, --lslow

Don't create a node, but print highest or lowest existing numbered version for the given name.


Print full documentation.


Attempt to create the next highest numbered version.


Where files are concerned, behave like --mknext but with the unnumbered filename's contents being copied to the new file. This can be useful when maintaining a file's most current state in an unnumbered or zero-numbered filename (e.g., "myfile" or "myfile0"), and with every other version numbered chronologically.

-v, --version

Print the current version number and exit.




John Kunze jak at ucop dot edu


Copyright 2009-2010 UC Regents. Open source BSD license.