Icon The Kermit Project   |   Now hosted by Panix.com
New York City USA   •   kermit@kermitproject.org
since 1981

C-Kermit's CHANGE Command

Frank da Cruz
January 30, 2016
Last update: Sun May 8 20:16:58 2022 (format)

The CHANGE command, new to C-Kermit 9.0.304, lets you replace strings in one or more text files with new strings in a way that is more convenient and less error-prone than changing each file by hand, and is more portable and flexible than using a Unix sed script or other platform-specific method.

Suppose (for example) you manage a website with thousands of files in a directory tree, many of which link to an offsite page whose URL has just changed. Now you can fix them all with a single C-Kermit command:

change /recursive ~/web/*.html www.oldname.com www.newname.com

The syntax of the CHANGE command is:

CHANGE [ switches ] filespec String1 [ String2 ]
The CHANGE command replaces all occurrences of string1 with string2 in the specified file or files. It works line by line; it does not do multiline or across-line substitutions (you can use the replacetextblock script for that). To remove strings from files, specify string2 as "" or omit string2. The filespec and strings can be given literally or you can use variables for them.

Square brackets indicate switches (explained below) that are optional. The filespec is a "file specification", which can be the name of a single file, possibly with a relative or absolute path included, or a "wildcard" pattern that uses special characters to match filenames, such as "*.html" to match all HTML files (see below for details about wildcards).

String1 and String2 should be enclosed in doublequotes "" or braces {} if if they contain spaces; for example, to update the copyright notice in a collection of C-language source files:

change *.[ch] "Copyright (C) 1985, 2015" "Copyright (C) 1985, 2016"
In the event that String1 or String2 already contain braces or doublequotes, especially if these are not balanced, some quoting may be required. Or you can assign the strings to variables and then use the variable names in the CHANGE command; example:
.a = {value="./
.b = {value="../
change *.html \m(a) \m(b)
Since the CHANGE command works line by line, only text files can be changed; C-Kermit automatically skips over binary files.

How the CHANGE command works

For each text file that matches the given filespec, the CHANGE command reads the original file line by line, changing all occurrences (if any) of String1 to String2 in each line, and writing the result to a result file.

Normally the result file is a temporary file, which is then renamed back to the original file's name, thus overwriting it. Other options explained below allow you to back up the original file or to write the result file into a different directory. Each of these options preserves a copy of the original file.

Temporary files are created in the directory indicated by Kermit's \v(tmpdir) variable (“show var tmpdir”). If the temporary directory does not exist, or none is specified, you'll get an error message. You can specify a temporary directory with the SET TEMP-DIRECTORY command, or by setting a environment variable (Unix) or symbol or logical name (VMS) such as TMP, TEMP, or TEMPDIR to the full path of the desired directory, to which you must have write access. If you haven't defined a temporary directory or an environment variable for this, C-Kermit uses the underlying operating system's convention, such as the /tmp directory in Unix.

All temporary files are deleted after use.

Switches

In Kermit's command language a switch is an optional command field that lets you modify the normal or default behavior of the command. The CHANGE command has lots switches:
/after:     /destination:   /modtime:       /recursive
/backup:    /dotfiles       /nodotfiles     /simulate
/before:    /except:        /norecursive    /smaller-than:
/case:      /larger-than:   /not-after:
/count:     /list           /not-before:
...for file selection (size, date, exception lists, dot-files), file disposition, directory traversal (flat or recursive), modification time of changed files (updated or preserved), and reporting of results.

File selection switches

These are handy when your file specificion is “wild”; that is, it contains wildcard characters and match more than one file. In the absence of instructions to the contrary, C-Kermit changes all the text files in the specified or current directory that match your file specification and that contain at least one instance of String1. But you can refine the selection using these switches in any desired combination:
/after:date-time
Only process files created or modified after the given date and time, which can be in almost any format, provided there are no embedded spaces, or if there are, that is is enclosed in doublequote or braces. Synonym: /since:. Examples:

/after:21-jan-2016_12:00:00 Contains no spaces
/after:"21 jan 2016 12:00:00" Contains spaces, use quotes
/after:{jan 21, 2016 12:00} Contains spaces, use braces
/after:"jan 21, 2016" No time is given, 0:00:00 is assumed
/after:1/21/2016 No time is given, 0:00:00 is assumed
/after:21/1/2016 21 is always a day, not a month
/after:YESTERDAY Symbolic date
/after:8:00 No date given; current date assumed
/after:8:00pm AM or PM can be specified
/after:20:00 Military time format can be used
/after:"TODAY +7days" offsets can be specified

etc etc. For complete details about C-Kermit's date/time formats, CLICK HERE.

/before:date-time
Only process files created or modified before the given date and time.
/not-after:date-time
Only process files created or modified on or before the given date and time. Synonym: /not-since:.
/not-before:date-time
Only process files created or modified on or after the given date and time.
/dotfiles
(Unix only) Do not skip files whose names begin with a period (.). Normally they are skipped.
/nodotfiles
(Unix only) Do not process files whose name begins with a period (.). This is the default action.
/except:filespec
Do not process files whose names match the given pattern; for example /except:old*.txt. The filespec can be the name of a file or a character string containing wildcards such as “*”, which matches any sequence of characters. It is also possible to specify a list of patterns or files to be excluded. See below for more about wildcard syntax.
/larger-than:number
Only process files that are larger than the given number of bytes (characters).
/smaller-than:number
Only process files that are smaller than the given number of bytes.
/recursive
Process not only the files in the current directory, but also the files in all the subdirectories of the current directory, and all the subdirectories of the subdirectories, and so on. In other words, process all files that meet the other criteria in the entire directory tree rooted in the current directory.
/norecursive
Process only files in the current (or specified) directory that meet the all the other given criteria, which is the normal procedure.

File disposition switches

Normally the CHANGE command modifies files in place; unless you tell Kermit otherwise, each original file that is modified by the CHANGE command is replaced by the changed version. If you wish to preserve the original files, two options are available:
/backup:directory-name
This lets you specify the name of a directory where a copy of each original file is to be stored. The CHANGE command then uses this directory to back up each file that is changed. The backup directory may not be the same as the destination directory (if any) or the source directory.
/destination:directory-name
This lets you specify the name of a directory where the new (changed) files will be stored. In this case, the original files stay where they are, the the changed files go into tbe specified directory, and no temporary files or directories are used. The destination directory may not be the same as the backup directory (if any) or the source directory.
These two switches are not mutually exclusive; you can use them both, in which case the original file stays as it is, the changed file appears in the destination directory, and a copy of the original file appears in the backup directory.
/modtime:{preserve, update}
Determines the modification timestamp for a file that is changed; "preserve" means to keep the file's original modification timestamp; "update" (which is the default action) means to set the file's modification timestamp to the date and time at which it was modified by the CHANGE command, but only if it was modified. Files that do not contain the search string (string1) are not disturbed in any way.

String selection switches

/case:{on,off}
When searching for strings to replace, require alphabetic case to match (ON), or ignore alphabetic case (OFF). The default action is ON, which requires the case of each letter to match. Thus "Hello" matches "Hello" but not "hello".

Action switches

/count:variablename
Sets the value of the given variable to the number of files that were changed.
/list
Reports which files are being changed. Without this switch the CHANGE command operates silently.
/simulate
Reports which files that would be changed without changing them.

Using switches

CLICK HERE to read complete details of the syntax and use of switches. But in brief...

Switches must be separated from other command fields and each other by blank space. There must not be any blank space between a switch and its argument. If a switch argument contains any spaces, it must be enclosed in doublequotes or braces. Switches can be combined in any desired manner, for example:

change /before:1-feb-2016 /not-before:1-jan-2016 *.txt December January
changes all occurrences of the word “December” to “January” in all files having modification timestamps in January of 2016.

If you include the same switch more than once in a single CHANGE command, the value of the last instance is used.

Lots of C-Kermit's other file transfer and management have the same or similar switches: SEND, GET, DIRECTORY, DELETE, COPY, RENAME, TOUCH, and so on.

C-Kermit's wildcard syntax

CLICK HERE for a thorough description description of C-Kermit's wildcards and pattern matching tools, with examples. But in brief...

A “wildcard” is a notation used in a filename to match multiple files. For example, in “send *.txt” the asterisk is a wildcard, the meaning in this case is “send all files in the current directory whose name ends with .txt”. Most Kermit commands that accept filenames also accepts wildcards, the exception being commands that are allowed to operate on only one file, such as TRANSMIT. C-Kermit accepts the following wildcards:

* (asterisk or "star") Matches any sequence of zero or more characters. For example, "ck*.c" matches all files whose names start with "ck" and end with ".c" including "ck.c".
? (question mark) Matches any single character. For example, "ck?.c" matches all files whose names are exactly 5 characters long and start with "ck" and end with ".c". When typing commands at the prompt, you must precede any question mark to be used for matching by a backslash (\) to override the normal function of question mark in interactive commands, which is to provide menus and file lists. You don't, however, need to quote filename question marks in command files (script programs).
[abc] Square brackets enclosing a list of characters matches any character in the list. Example: ckuusr.[ch] matches ckuusr.c and ckuusr.h.
[a-z] Square brackets enclosing a range of characters matches any character in the range; a hyphen (-) separates the low and high elements of the range. For example, [a-z] matches any letter from a to z.
[acdm-z] Lists and ranges may be combined. This example matches a, c, d, or any letter from m through z.
{string1,string2,...} Braces enclose a list of strings to be matched. For example: ck{ufio,vcon,cmai}.c matches ckufio.c, ckvcon.c, or ckcmai.c. The strings may themselves contain *, ?, [abc], [a-z], or other lists of strings.

To force a special pattern character to be taken literally, precede it with a backslash, e.g. [a\-z] matches a, hyphen, or z rather than a through z. Or tell Kermit to SET WILDCARD-EXPANSION OFF before entering or referring to the filename (but then set it back ON afterwards to restore the normal behavior).

Similar notation can be used in general-purpose string matching; for example in the IF MATCH command:

if match ckufio.c {{ck[cuw]*.[cwh],makefile}} {
    echo "It's a C-Kermit source file"
}
Type HELP PATTERNS at the C-Kermit prompt for details. Also see HELP SET MATCH.

  C-Kermit's CHANGE command / kermitproject.org /