FileUtils plugin for Take Command / TCC / TCC/LE
beta version 0.93.1 2025-10-09
Charles Dye
Purpose:
This plugin adds a few file- and drive-related features.
BOTTOMUP visits directories recursively,
from innermost to outermost, and runs a command in each — like an
inside-out GLOBAL.  BSPLIT
splits files into smaller files.  DIRCMP
compares two directories and list items which appear in one but not the
other.  It can optionally also compare files’ sizes, time stamps,
attributes, and contents.  EMPTIES
lists, and optionally removes, empty subdirectories.
FILEINFO  displays lots of information
about matching files, including checksums, version information, image file
information, and Windows properties.  HEXDUMP
dumps the contents of files in a variety of different formats.  RENCASE
changes the case of filenames.  SWAPNAMES
exchanges two files. 
@IMGINFO returns information about
an image file.  @RPTARGET returns the
target of a reparse point.  @WINPROP
returns a Windows property of a file. 
Installation:
To use this plugin, copy FileUtils.dll
and FileUtils.chm to some known location on
your hard drive.  (If you are still using the 32-bit version of Take Command,
take FileUtils-x32.dll instead of
FileUtils.dll.)  Load the .DLL file with a
PLUGIN /L command, for example: 
plugin /l c:\bin\tcmd\test\fileutils.dll
If you copy these files to a subdirectory named PlugIns within your Take Command program directory, the plugin will be loaded automatically when TCC starts.
Plugin Features:
Syntax Note:
The syntax definitions in the following text use these conventions for clarity:
BOLD CODE | indicates text which must be typed exactly as shown. | 
CODE | indicates optional text, which may be typed as shown or omitted. | 
| Bold italic | names a required argument; a value must be supplied. | 
| Regular italic | names an optional argument. | 
| ellipsis… | after an argument means that more than one may be given. | 
Examples are shown in a gray box:
rem   This is an example: 
fileinfo *.txt;*.cpp
Some command options take an argument.  These are shown with a colon between the option
and its argument:  /A:arg 
If you like, you may substitute an equals sign for the colon:  /A=arg 
This is handy if the arg is a filename, and you want to use tab completion to
enter the filename. 
Or you can omit the colon:  /Aarg 
New Commands:
APPPATHS — List, set, or remove AppPaths
entries. 
Syntax:
APPPATHS /D:dir /E /K /M /N:flags /P /Q /R:file /U /X /Y app.exe=fullpath
/D:dir | specify the default directory for app.exe | 
/E | suppress error messages | 
/K | show counts | 
/M | in HKEY_LOCAL_MACHINE (system-wide) | 
/N:flags | disable features: | 
    C — disable highlight | |
    E — suppress error messages | |
    H — don’t show hive tags | |
    W — don’t check existence of files and directories | |
/P | page output | 
/Q | quietly | 
/R:file | read entries from a text file | 
/U | in HKEY_CURRENT_USER (per-user) | 
/X | expand REG_EXPAND_SZ values | 
/Y | yes to all prompts | 
| app.exe | the program to list/set/delete an entry for | 
| fullpath | the complete pathname to the .EXE file | 
Any options must come before any app.exe on the command line.
This command can be used in four different ways: to list existing AppPaths entries, to create or change an entry, to remove an AppPaths entry, or to read and set entries from a file. Different options make sense in each of these modes.
To list AppPaths entries:
APPPATHS /K /M /P /U /X app.exe
The app.exe should end in .EXE;
it may contain wildcards.  If you do not specify an app.exe,
APPPATHS will list all entries.  If you do not specify either /M or
/U, the default is to list entries from both keys. 
To set an AppPaths entry:
APPPATHS /D:dir /E /M /Q /U /X /Y app.exe=fullpath
app.exe is required; it should end in
.EXE.  If you do not specify either /M or /U,
the default is /M. 
If you do not specify a /D:dir, the
default is the program’s directory from fullpath. 
Strings are written as type REG_SZ, unless you specify
/X.  With /X, if either your fullpath
or your /D:dir contains at least one
percent sign, then the string(s) with percent signs will be written as type
REG_EXPAND_SZ. 
To remove an AppPaths entry:
APPPATHS /E /M /Q /U /Y app.exe=
app.exe is required; it should end in
.EXE.  If you do not specify either /M or /U,
the default is /M. 
To read and set AppPaths entries from a file:
APPPATHS /E /M /Q /R:file /U /X /Y
The file should contain one entry per line, in the format:
app1.exe = fullname1
app2.exe = fullname2
app3.exe = fullname3
…
Blank lines and lines beginning with a semicolon are ignored.  All other lines must
be in app.exe=fullname
format, or they will be flagged as errors. 
When setting entries from a file, no attempt is made to canonicalize file and directory names, or to check whether they actually exist. Filenames are simply written to the registry as is.
All entries will be made in the same registry hive, according to /M or
/U; if neither is specified, the default is /M.  There is no
provision for specifying default directories; the default directory for each entry will
be fullname’s directory. 
Strings are written as type REG_SZ, unless you specify
/X.  With /X, strings containing percent signs will be
written as REG_EXPAND_SZ; strings without percent signs will still
be created as REG_SZ. 
BOTTOMUP — Visit subdirectories
recursively, deepest first, and run a command in each. 
Syntax:
BOTTOMUP /B /H /I /N /P /Q /S:dir command
/B | bare directory display | 
/H | include hidden directories | 
/I | ignore exit codes | 
/N | do not visit or search junctions | 
/P | prompt before running the command | 
/Q | do not display directory names | 
/S:dir | specify the top-level directory | 
This command works much like GLOBAL, only inside-out.  It visits
subdirectories recusively, deepest first, and runs the specified
command in each.  It ends up — and runs
the command a final time — in the original current directory. 
TCC expands the command line before BOTTOMUP sees it.  You will
need to double any percent signs, and use escapes or strong quotes to protect
any problem characters in the command.  This is different than GLOBAL,
but unavoidable — I cannot prevent TCC from performing variable
expansion before the plugin command is called. 
The command is required.  If you want to do
nothing recursively, use REM. 
By default, BOTTOMUP will abort if the
command returns a nonzero exit code, or if it
cannot change the current directory to any subdirectory in the tree.
If /I is specified, both of these situations will be ignored and
processing will continue. 
rem    Trivial demo:
bottomup /q echo Now I'm in "%%_cwd" !
rem    An inside-out directory listing:
bottomup /i /q dir /f /h /ne
BSPLIT — Split files into
smaller files. 
Syntax:
BSPLIT /D:dir /E /F:n /N:n /O /P /Q /S:size /X:prefix filename…
/D:dir | output directory | 
/E | no error messages | 
/F:n | extension numbering format | 
/N:n | number of splits | 
/O | overwrite existing files | 
/P | output to source file’s path | 
/Q | quietly | 
/S:size | split size | 
/X:prefix | extension prefix | 
| filename… | files to split | 
BSPLIT divides a file into multiple smaller files.  You can split at a
specified size (/S:), or into a specified number of files (/N:).
You cannot combine /N: and /S:. 
You must supply a filename. Wildcards and directory aliases are supported, and you may have more than one filename on the command line. The output directory defaults to the current directory.
BSPLIT is short for “binary split”.  It splits files by byte size.
It does not support splitting by lines or characters.  If the input file contains text it
may be divided within a line, or possibly even within a character. 
/D:dir specifies
the directory that the split files will be written to.  If this directory does not exist,
BSPLIT will attempt to create it for you. 
/P writes the split files to the same directory
as the original file.  It’s like a shorthand for
/D:"%@PATH[filename]".
If you don’t specify either /D: or /P, the default is to write
the split files to the current directory. 
/F:n lets you change
the way the output files are numbered.  The formats are: 
0 | two decimal digits | 
1 | three decimal digits | 
2 | four decimal digits | 
3 | two hexadecimal digits | 
4 | three hexadecimal digits | 
5 | four hexadecimal digits | 
6 | two letters (base 26) | 
7 | three letters (base 26) | 
8 | four letters (base 26) | 
Add 32 for uppercase.  If you don’t specify a format, the default is three
decimal digits.  If you specify a prefix with /X:, the prefix will be
inserted at the start of the extension. 
/S:size specifies the
size of the output files.  You may give the size as: 
| n | bytes | 
nk | thousands of bytes | 
nK | kilobytes (1,024 bytes) | 
nm | millions of bytes | 
nM | megabytes (1,048,576 bytes) | 
ng | billions of bytes | 
nG | gigabytes (1,073,741,824 bytes) | 
/N:n instead splits
the file into n more-or-less equally-sized pieces.  You cannot
combine /N: and /S:. 
rem    Break BigFile into 500-kilobyte files:
bsplit /s:500K bigfile
rem    Break BigFile into four more-or-less equal files:
bsplit /n:4 bigfile
CFILES — List files common to two
directories. 
Syntax:
CFILES /C /K /L /M:wildspec /P /S here there
/C | compare last-write times | 
/K | show counts | 
/L | show a legend at the end (for use with /C) | 
/M:wildspec | include only files matching wildspec | 
/P | page output | 
/S | search in subdirectories | 
| here | optional; defaults to the current directory | 
| there | required | 
CFILES lists files which exist in both of two directories, called
here and there.  You must specify at least one.  If you provide two
directories, the first one is here and the second is there.  If you
only give one, it’s there and the current directory is here. 
If you use /C, CFILES will highlight files with
different last-write times.  The file times are rounded down to the nearest second
before comparison.  A left arrow ← indicates that the file here is
the newer of the two; a right arrow → means that the file there
is newer. 
rem   List files present in both the current directory
rem   and C:\Latest, and compare time stamps:
cfiles /c c:\latest\
DATEDIR — Lists files and subdirectories, 
sorted by date and time. 
Syntax:
DATEDIR /A:attribs /B /E /F /F:"format" /L /M /N:flags /P /Q /R /S /T /T:flags file…
/A:attribs | filter by attributes | 
/B | bare: filenames only, no dates or times | 
/E | uppercase | 
/F | show full paths (implied by /S) | 
/F:"format" | time format string, as per @DATEFMT | 
/L | lowercase | 
/M | show final counts at the end | 
/N:flags | disable features; see below | 
/P | page output | 
/Q | quote filenames | 
/R | reverse sort order (newest first) | 
/S | search in subdirectories | 
/T | show times; the default is to show dates only | 
/T:flags | time options; see below | 
| file… | wildcards and directory aliases are supported | 
If you do not give any filespecs, * is assumed by default.  If
you do not give any /A:attribs, the
default is to list files and subdirectores which do not have the hidden or system
attributes. 
DATEDIR lists matching files and subdirectories ordered by date
and time, oldest first.  If you give multiple filespecs or use /S to
search into subdirectories, all matching files will be sorted together.  By default,
DATEDIR shows only the dates of matching files; I find that in most
cases, dates alone are enough to distinguish between different versions of the same
file.  You can add /T to show times along with dates, or use
/F:format to roll your own display format. 
/N: disables features.  These flags
can be combined: 
D | do not search into hidden directories | 
F | suppress file-not-found errors | 
J | do not search into junctions | 
Z | do not search into system directories | 
/T: selects which time stamp to
display and sort on, and how to display it.  Flags may
include: 
A | show the last-access time stamp | 
C | show the creation time stamp | 
W | show the last-write time stamp | 
D | default: localize time stamps as TCC and CMD.EXE do | 
L | local times, taking DST time changes into account | 
U | Coordinated Universal Time | 
F | show fractional seconds (implies /T) | 
The default is to use the last-write time, localized as TCC and CMD do.  D, 
L, U, and F modify the way times are
displayed; they do not affect sorting. 
rem   List all copies of conlist.cpp, sorted by age:
datedir /s c:\code\conlist.cpp
DIRCMP — Compare two
directories. 
Syntax:
DIRCMP /A /C /D /M /P /R /S /T /X dir1 dir2
/A | compare attributes of items which exist in both dir1 and dir2 | 
/C | compare file contents | 
/D | disable highlight | 
/M | do not display the footers | 
/P | page output | 
/R | compare directories recursively | 
/S | compare sizes of files which exist in both directories | 
/T | compare time stamps of files which exist in both directories | 
/X | reverse operation — reports only items which exist in both directories | 
| dir1 | the first directory; directory aliases are supported | 
| dir2 | the second directory; directory aliases are supported | 
dir1 and dir2 are both required. Wildcards are not allowed; you must name two unambiguous directories.
/A compares attributes when a file or
subdirectory exists in both dir1 and
dir2.  Only the read-only, archive, hidden, and
system attributes are compared.  The more exotic attributes will be ignored. 
/C compares the contents of files which
appear in both directories.  Both files are opened, then data is read and
compared, byte-for-byte.  This option can slow DIRCMP down
considerably!  If the command is unable to read from either file, the files
are considered the same. 
/S compares file sizes when a file exists
in both locations.  Only files are tested.  The relevant Windows APIs do not
report sizes for subdirectories. 
/T compares time stamps when a file
exists in both locations.  Only the last-write time stamp is compared, and the
comparison is fuzzy; differences of less than two seconds may be ignored.  Only
time stamps of files are compared; this option does not test
subdirectories. 
/X reverses DIRCMP’s
operation and reports only items which exist in both locations.  If you combine
/X with /A, /C, etc. then only
items with matching attributes, contents, and so on will be listed. 
Note that /R, not /S,
controls recursion.  Recursion is only performed where subdirectories with the
exact same name exist in both dir1 and
dir2. 
Mismatches are reported with a note in brackets:
[1] | The item exists in dir1 but not in dir2. | 
[2] | The item exists in dir2 but not in dir1. | 
[A] | The item has different attributes in dir1 and dir2. | 
[C] | The file has different contents in dir1 and dir2. | 
[S] | The file has different sizes in dir1 and dir2. | 
[T] | The item has different time stamps in dir1 and dir2. | 
The letters may be combined; e.g. [ST] would mean that
the items have different sizes and time stamps. 
Items which exist in one directory, but not the other, are always reported. There is no option to suppress this feature.
If a file exists in dir1 and a subdirectory of the same name exists in dir2 — or vice versa — then both will be reported as mismatches.
dircmp /r /s "%userprofile\Documents" d:\backup\docs\
EMPTIES — List or remove empty subdirectories. 
Syntax:
EMPTIES /J /M /P /Q /R /Y dirname…
/J | allow recursion into reparse points | 
/M | no footers | 
/P | page output | 
/Q | quietly (only useful with /R) | 
/R | remove empty directories | 
/Y | yes to all prompts | 
| dirname… | directory aliases are supported | 
If no directory names are given, EMPTIES searches the current directory
by default. 
See also:  the @DIREMPTY function. 
FILEINFO — Display information
about files. 
Syntax:
FILEINFO /A:attribs /C:hash /D /N:flags /O:flags /P /S /T:flags /[range] file…
/A:attribs | filter by attributes | 
/C:hash | checksum and hash algorithms; see below | 
/D | disable highlight | 
/N:flags | disable features; see below | 
/O:flags | omit features; see below | 
/P | page output | 
/S | look in subdirectories for matching files | 
/T:mode | time display mode; see below | 
/[range] | many range options are supported | 
| file | wildcards, directory aliases, include lists, and @file lists are supported | 
FILEINFO displays information about files; go figure.  By
default, the information shown includes the full, canonical filename; any
version information; any TCC file description; the file size, date and time
stamps, and attributes; CRC32 and MD5 checksums; 4DOS file descriptions;
executable types; Windows properties; and document summary information. 
/N: disables features.  These flags
can be combined: 
C | disable highlight | 
D | do not search into hidden directories | 
F | suppress file-not-found errors | 
J | do not search into junctions | 
Z | do not search into system directories | 
/O: omits classes of information.
These flags can be combined: 
A | omit attributes | 
C | omit checksums | 
D | omit file descriptions | 
E | omit text file encoding | 
F | omit TTF font info | 
H | omit file version header | 
I | omit image file info | 
L | omit link targets | 
N | omit NTFS streams info | 
P | omit Windows properties | 
R | omit file type information | 
Q | do not use fancy Unicode quotes | 
S | omit document summary information | 
T | omit time stamps | 
U | do not resolve AppX execution aliases or symlinks to .exe files | 
V | omit version information | 
X | omit executable information | 
Z | omit sizes | 
Omitting information can make the command faster and reduce the amount
of text that is displayed.  In particular, computing checksums for very large
files can be slow; using /OC will save this time. 
/C: specifies the type of checksum
or hash displayed by FILEINFO.  The available algorithms are: 
CRC32 | CKSUM | MD5 | 
SHA1 | SHA256 | SHA384 | 
SHA512 | 
You can give more than one, separated by commas.  If no /C:
is given, the default is /C:CRC32,MD5. 
/T: selects which time stamps to
display, and how to show them.  Flags may
include: 
A | show the last-access time stamp | 
C | show the creation time stamp | 
M | show the last-modified time stamp | 
D | default: localize time stamps as TCC and CMD.EXE do | 
L | local times, taking DST time changes into account | 
U | Coordinated Universal Time | 
F | show fractional seconds; the default is not to show them | 
A, C, and M may be combined.  If
none is given, the default is to display all three time stamps.  Only one
of D, L, and U should be given; the
default is D. 
fileinfo "%_cmdspec"
FILEUTILSHELP — Open the
FileUtils plugin help file. 
Syntax:
FILEUTILSHELP /C /F /S /S:text /V topic
/C | select the ‘Contents’ tab | 
/F | select the ‘Favorites’ tab | 
/S | select the ‘Search’ tab | 
/S:text | select the ‘Search’ tab and search for text | 
/V | show detailed plugin version info | 
| topic | the page to display | 
The FILEUTILSHELP command will locate and open this
plugin’s help file.  In most cases, the internal HELP
command, and the F1 and Ctrl-F1 keys, will be
more convenient.  The main advantage to this command is that it can be used to
open the help file to any desired topic, not only to the names of commands,
functions, and variables. 
Note that any /C /F or /S must
precede any topic on the command line.  (This
command has a very simple-minded parser.) 
HEXDUMP — Display files or
standard input to standard output as hex. 
Syntax:
HEXDUMP /A:attr /B /BE /C:start /CP:n /D /E:end /F:n /H /HH /I /J /K:n /LE /M:max /ML:lines /N:flags /P /Q /S /U /W /X /Z:char filename…
/A:attr | filter by attributes | |
/B  or  /1 | dump bytes | ✔ | 
/BE | big-endian | |
/C:start | start address | |
/CP:n | code page to use for non-Unicode text | |
/CR | use CR line ends | |
/CRLF | use CR/LF line ends | ✔ | 
/D  or  /4 | dump doublewords (four-byte integers) | |
/E:end | end address | |
/F:n | numeric base for values | 16 | 
/H | display filenames | |
/HH | display filenames, sizes, and text encodings | |
/I | include a final summary line | |
/J | highlight alternate lines | |
/K:n | bytes per line | |
/LE | little-endian | ✔ | 
/LF | use LF line ends | |
/M:max | maximum number of bytes to display | |
/ML:lines | maximum number of lines to dump | |
/N:flags | disable features | |
/P | page output | |
/Q  or  /8 | dump quadwords (eight-byte integers) | |
/S | search into subdirectories for matching files | |
/U | Unixy mode | |
/UC | uppercase hexadecimal addresses and values | |
/W  or  /2 | dump words (two-byte integers) | |
/X | use control pictures for ASCII control characters | |
/Z:char | set the replacement character | 0xB7 | 
Filenames may be specified on the command line, or text may be redirected
or piped into HEXDUMP.   Wildcards, directory aliases, and
CLIP: are supported. 
If you do not specify any filenames, HEXDUMP will read from
standard input.  If standard input is not redirected from a file or pipe,
HEXDUMP will read from the keyboard; type Ctrl-Z
and then Enter to finish. 
If you want to pipe to HEXDUMP, remember that pipes open a
new shell.  You must either ensure that this plugin is loaded in the new
shell, e.g. by copying its .DLL file to the PlugIns
directory; or else use an in-process pipe with the |!
syntax. 
HEXDUMP may fail on extremely large files (more than a
gigabyte or two).  The exact upper limit will vary depending on your
processor type and Windows edition.  X64 Windows will allow much larger
files than X86 Windows. 
/F:n
lets you specify the numeric base for displaying values.  Legal values are: 
/F:O  or  /F:8 | octal | 
/F:D  or  /F:10 | decimal | 
/F:S  or  /F:+ | signed decimal | 
/F:H  or  /F:16 | hexadecimal (the default) | 
Addresses are always shown in hexadecimal.
8 | do not show dashes between bytes of UTF-8 characters | 
B | do not write a BOM (useful when redirecting to a Unicode file) | 
C | no highlight | 
D | do not search into hidden directories (with /S)  | 
F | suppress file-not-found error messages | 
I | do not display the address field | 
J | do not search into junctions (with /S)  | 
L | do not add a blank line at the end of each file | 
Q | no fancy Unicode quotes in the header or summary lines | 
T | do not display the text field (i.e. characters) | 
U | do not display non-ASCII characters in the text field | 
Z | do not search into system directories (with /S)  | 
/C:start,
/E:end, and
/M:max let you specify a start
address, an end address, and a maximum number of bytes to dump.  You can
enter these values as decimal, or hexadecimal with a leading 0x.
You may give none, one, or any combination of these options. 
/C:, /E:, and /M: values are
all in bytes by default.  You can append one of the following letters: 
b | bytes | 
w | words | 
d | doublewords | 
q | quadwords | 
k | thousands of bytes | 
K | kilobytes (210 or 1,024 bytes) | 
m | millions of bytes | 
M | megabytes (220 or 1,048,576 bytes) | 
g | billions of bytes | 
G | gigabytes (230 or 1,073,741,824 bytes) | 
Note that k K m M g and G are case-sensitive. 
If you don’t give any of these suffixes, the value is in bytes — even if you are displaying words or doublewords. There are no alignment checks; you can dump misaligned data if you wish.
/C: and /E: allow you to pass a negative number to 
specify the address as an offset from the end of the file, e.g. /C:-1K
to dump only the last kilobyte of the file.  /M: does not allow 
negative numbers. 
/K:n
lets you specify the number of bytes to display per line.  If you don’t
give any /K:, the command will pick its own value based on the
console width (if output is to the console), or a default line width of
100 characters if output is redirected.  Again, this value is in bytes,
even if you are displaying data as words or doublewords.  The value
n must be between 8 and 80, and a multiple of
8. 
/K:0 sets the line length based on the console width, even
in cases where HEXDUMP normally would not do so:  when output
is redirected or piped, e.g. piping to LIST; or in
Unixy mode. 
/ML:lines
lets you set a maximum number of data lines to dump.  Any header or summary lines
are not counted. 
/Z:char
lets you specify the replacement character, which is shown in the text
field in place of control characters.  The default is normally a middle dot
·    You may give either a literal character or a character value.  All
three of the following are equivalent: 
•  /Z:* | (literal character) | 
•  /Z:42 | (decimal value) | 
•  /Z:0x2a | (hexadecimal value) | 
Your replacement character may not be alphanumeric or a control
character.  /Z by itself will use a space as the replacement
character. 
/U selects Unixy mode:  the
output format is adjusted to look more like hexdump utilities
found on various flavors of Unix.  16 bytes of data are displayed per line,
unless you set a diffent value with /K:n.
Multiple lines with the same data are replaced with a single asterisk.
The default replacement character is a period, unless you set a different
one with /Z:char. 
/U only makes a few cosmetic adjustments to
HEXDUMP’s output format.  Its basic operation is
unchanged, and the output may not be an exact match for any particular
Unix utility. 
rem   Dump the file Build.txt :
hexdump /hh /i /x build.txt
RENCASE — Change the case of
filenames. 
Syntax:
RENCASE /A:attribs /E /L /N /N:flags /S /U /W /X:luw /[range] file…
/A:attribs | filter by attributes | 
/E | no error messages | 
/L | change the base name (all but the extension) to lowercase | 
/N | not really | 
/N:flags | D no hidden directories, J no junctions, Z no system directories | 
/S | look in subdirectories for matching files | 
/U | change the base name (all but the extension) to uppercase | 
/W | change the base name (all but the extension) to word case | 
/X:luw | change the extension to upper/lower/word case | 
/[range] | many range options are supported | 
| file… | wildcards, directory aliases, etc. supported | 
RENCASE renames files, changing the case of letters.  Filenames
are handled as two parts:  the base name (everything before the last period),
and the extension (everything after).  Options /L, /U,
and /W affect the base name, and /X: affects the
extension. 
If no action is specified (none of /L, /U, /W,
or /X:), the default is /L. 
rencase /l /x:l *.html
SWAPNAMES — Exchange two
files. 
Syntax:
SWAPNAMES /D /Q /X file1 file2
/D | file1 and file2 are directories, not files | 
/Q | quietly | 
/X | check that file1 and file2 have the same file type | 
| file1, file2 | required; wildcards not allowed | 
This command does a double rename. It renames file1 as file2, and vice versa. It only renames one pair of files; wildcards are not supported.
/X gets both files’ extensions, and reads their default
handlers from the registry.  It allows the rename only if both extensions are
the same, or if both have the same handler.  For example, you can swap a
.txt file with a .log
file only if they have the same handler.  /X is ignored with
/D. 
swapnames myfile.cpp myfile.bak
New Functions:
@CMPTIME — Compares
timestamps of two files. 
Syntax:
%@CMPTIME[file1,file2,which]
| file1 | the first file to examine | 
| file2 | the second file to examine | 
| which | A, C, or W; the default is W | 
Both files must exist. Directory aliases are supported.
Return values:
| -1 | if file1 is older than file2, | 
| 0 | if both files are the same age, | 
| 1 | if file1 is newer than file2. | 
if %@cmpfile[%_cmdspec,%_ininame] == 1 echo %_cmdspec is newer than %_ininame!
@CMPVER — Compares version
numbers of two files. 
Syntax:
%@CMPVER[file1,file2,flags]
| file1 | the first file to examine | 
| file2 | the second file to examine | 
| flags | 1: do not assume 0.0.0.0 | 
Both files must exist.  Directory aliases are supported.  If either file
does not contain version information, this function will assume
0.0.0.0 — unless flags is
1, in which case the function will give an error instead. 
Return values:
| -1 | if file1 has a lower version number than file2, | 
| 0 | if both files are the same version, | 
| 1 | if file1 has a higher version number than file2. | 
echo %@cmpver[%@search[notepad.exe],%@search[ping.exe]]
@DDEPTH — Returns the depth
of a file or subdirectory. 
Syntax:
@DDEPTH[file]
| file | directory aliases and relative paths are okay | 
Returns 0 for items in the root directory, 1 for items in a subdirectory, 2 for items in a sub-subdirectory, and so on. File need not actually exist.
echo %@ddepth[c:\foo\bar\readme.txt]
@DIREMPTY — Checks whether a
directory is empty. 
Syntax:
@DIREMPTY[dirname]
| dirname | the directory to check | 
If dirname is a directory and it is empty,
@DIRNAME returns 1.  If dirname
is not a directory, if it isn’t readable, or if it contains anything other than
. and .., then
@DIRNAME returns 0. 
See also:  the EMPTIES command. 
@DIRREADABLE — Tests whether the
current user can read from a directory. 
Syntax:
@DIRREADABLE[dirname]
| dirname | the directory to test | 
Returns 1 if you can read from the specified directory,
0 if not. 
See also:  the @DIRWRITABLE function. 
@DIRWRITABLE — Tests whether the
current user can write a directory. 
Syntax:
@DIRWRITABLE[dirname]
| dirname | the directory to test | 
Returns 1 if you can write to the specified directory,
0 if not. 
See also:  the @DIRREADABLE function. 
@DRIVEBUS — Returns the
bus type of a given local drive. 
Syntax:
%@DRIVEBUS[drive]
| drive | the drive letter; the colon is optional | 
@DRIVEBUS returns an integer bus type:  4 IEEE 1394, 7 USB, etc.
@FILEVER — Returns the
version number of a file. 
Syntax:
%@FILEVER[file,flags]
| file | the first file to examine | 
| flags | 1: do not assume 0.0.0.0 | 
File must exist.  Directory aliases are
supported.  The version number will be returned in the format
major.minor.build.private.
If the file does not contain version information, the return value will be
0.0.0.0 — unless flags is
1, in which case the function will give an error instead. 
This value is always four integers, separated by periods (not your local
decimal character) and without leading zeroes or spaces.  It’s a more
consistent format than the version strings returned by @VERINFO,
which may contain whatever the programmer fancies. 
echo %@filever[%_cmdspec]
@FINDDRIVE — Finds a drive
matching the given criteria. 
Syntax:
%@FINDDRIVE[label,serial,minsize,maxsize,bus]
| label | wildcards are supported | 
| serial | up to 8 hex digits | 
| minsize | suffixes k, K, m, M, etc. supported | 
| maxsize | suffixes k, K, m, M, etc. supported | 
| bus | 4 IEEE 1394, 7 USB, etc. | 
@FINDDRIVE returns the drive letter (with a colon) of the first
drive it finds which meets all of the specified criteria.  You must specify at
least one. 
@IMGINFO — Returns information about
an image file. 
Syntax:
%@IMGINFO[n,filename]
| n | which information to return; see below | 
| filename | the image file to examine | 
If filename does not exist, is not an image file, or cannot be
read, you’ll get an error message.  If you request EXIF data which is not present in
the file, @IMGINFO will return the string N/A. 
| n: | Returns: | 
| 0 | image resolution, width × height | 
| 1 | image width (pixels) | 
| 2 | image height (pixels) | 
| 3 | horizontal resolution (DPI) | 
| 4 | vertical resolution (DPI) | 
| 5 | bits per pixel | 
| 6 | image format (string) | 
| EXIF data: | |
| 10 | image orientation | 
| 11 | date and time | 
| 12 | date and time (original) | 
| 13 | date and time (digitized) | 
| 14 | author | 
| 15 | description | 
| 16 | copyright | 
| 17 | software | 
| 18 | camera make | 
| 19 | camera model | 
@ISABATCH — Looks for a
matching batch file. 
Syntax:
%@ISABATCH[file,path,flags]
| file | the command to search for; no path, no extension, no wildcards | 
| path | directories to search; defaults to %PATH | 
| flags | bitmapped: 1: search current dir before path; 2: also search AppPaths; 128: return filename | 
@ISABATCH searches for a matching command, and returns a
numeric value: 
| 0 | no matching command was found | 
| 0 | the first matching command is not a batch (.com or .exe) | 
| 1 | the first matching command is a .btm | 
| 2 | the first matching command is a .cmd | 
| 3 | the first matching command is a .bat | 
The flags value lets you alter the function’s operation:
| 1 | search the current directory before the search path | 
| 2 | search AppPaths after the search path | 
| 128 | return the first matching filename, not a numeric value | 
If flags is not specified, it defaults to 1.
You can specify a different list of directories to search with path. Separate directories with semicolons (not commas!) and quote any directory which contains a space, comma, semicolon, or other troublesome character.
iff %@isabatch[empire] == 0 then
    echo Empire is not a batch file.
else
    echo Empire is a batch file:  %@isabatch[empire,,128]
endiff
@NEWEST — Returns the newest matching
file. 
Syntax:
%@NEWEST[/A: /F /S wildspec]
/A:attr | filter by attributes | 
/F | return the full pathname (/S implies this option) | 
/S | search into subdirectories | 
| wildspec | defaults to * | 
With no parameters, @NEWEST returns the most recent file in the
current directory.  If no matching files are found, @NEWEST returns
an empty string. 
echo %@newest[*.cpp]
@RANDFILE — Picks a file at
random and returns its filename. 
Syntax:
%@RANDFILE[/A:attribs /S /[range] wildspec]
| wildspec | required; directory aliases are supported | 
/A:attribs | filter by attributes; use /A:D to find subdirectories instead of files | 
/S | search for matching files in subdirectories | 
/[range] | many range options are supported | 
| wildspec | required; directory aliases are supported | 
@RANDFILE makes a list of files matching the given
wildspec, picks one at random, and returns a
complete pathname.  If no files match the wildspec,
this function returns an empty string. 
•  Note: Enumerating all matching files can take a long time, especially
if you use /S. 
@RPTARGET — Returns the target
of a reparse point. 
Syntax:
%@RPTARGET[filename]
| filename | the reparse point to examine | 
This function effectively combines the capabilities of @JUNCTION
and @SYMLINK.  Currently symlinks (relative and absolute), junctions,
and AppX execution aliases are supported.  No wildcards, directory aliases, or
other funny stuff.  @RPTARGET only takes one argument.  There is no
need to quote it, though you can if you want to. 
echo %@rptarget[%userprofile\start menu]
@TTFCOUNT — Returns the number
of TrueType fonts in a file. 
Syntax:
%@TTFCOUNT[filename]
| filename | the file to examine | 
For ordinary .TTF font files, @TTFCOUNT
will return 1.  For font collections (.TTC
files), it returns the number of fonts in the file.  For other file types, it returns
0. 
@TTFINFO — Returns text information
from a TrueType file. 
Syntax:
%@TTFINFO[filename,NameID,index]
| filename | the file to examine | 
| NameID | the NameID of the string to return | 
| index | the zero-based font number within the file | 
The NameID identifies the string to return. See e.g. Microsoft’s documentation for a complete list. Here are some of the most useful values:
0 | copyright | 
1 | font family name | 
2 | font subfamily name | 
4 | complete font name | 
5 | version | 
8 | manufacturer | 
9 | designer | 
10 | description | 
13 | licensing information | 
16 | typographic family name | 
17 | typographic subfamily name | 
If you do not supply a NameID, @TTFINFO
will try two ways to return the font’s name.  First it will look for the 
full font name, string #4 above.  If string #4 is not found, it will return a
combination of the font family name, #1, and the subfamily name, #2. 
The index value only applies to TrueType font
collections — .TTC files.  It must be
less than the number of fonts present in the file.  For example, if
MSGothic.ttc contains three fonts, then
index may be 0, 1, or
2 to select the first, second, or third font in the file.  If
index is greater than or equal to the number of
fonts in the file, @TTFINFO will return an empty string.
Index is ignored for regular .TTF
files. 
@WINPROP — Returns a Windows
property for a file. 
Syntax:
%@WINPROP[n,filename]
| n | which property to return | 
| filename | the file to examine | 
If filename does not exist, you’ll get an error
message.  If the file cannot be read or the specified property does not exist,
@WINPROP will return an empty string. 
| n | Returns: | 
| Core properties | |
| 0 | System.Author | 
| 1 | System.Comment | 
| 2 | System.Copyright | 
| 3 | System.FileDescription | 
| 4 | System.FileVersion | 
| 5 | System.ItemAuthors | 
| 6 | System.ItemNameDisplay | 
| 7 | System.Keywords | 
| 8 | System.Rating | 
| 9 | System.Subject | 
| 10 | System.Title | 
| 11 | System.Trademarks | 
| Media properties | |
| 20 | System.Media.AuthorUrl | 
| 21 | System.Media.CreatorApplication | 
| 22 | System.Media.CreatorApplicationVersion | 
| 23 | System.Media.DateEncoded | 
| 24 | System.Media.DateReleased | 
| 25 | System.Media.Duration | 
| 26 | System.Media.Producer | 
| 27 | System.Media.Publisher | 
| 28 | System.Media.SubTitle | 
| 29 | System.Media.Year | 
| Music properties | |
| 40 | System.Music.AlbumArtist | 
| 41 | System.Music.AlbumID | 
| 42 | System.Music.AlbumTitle | 
| 43 | System.Music.Artist | 
| 44 | System.Music.Composer | 
| 45 | System.Music.Conductor | 
| 46 | System.Music.DisplayArtist | 
| 47 | System.Music.Genre | 
| 48 | System.Music.Mood | 
| 49 | System.Music.Period | 
| 50 | System.Music.TrackNumber | 
| Audio properties | |
| 60 | System.Audio.ChannelCount | 
| 62 | System.Audio.EncodingBitrate | 
| 66 | System.Audio.SampleRate | 
| 67 | System.Audio.SampleSize | 
New Variables:
_FWDRIVES — Returns a list
of drives connected to IEEE 1394 ports. 
Syntax:
%_FWDRIVES
If more than one drive is returned, they will be separated with spaces.
for %drive in ( %_fwdrives ) do vol %_drive
_K32VER — Returns the version
number of Kernel32.dll. 
Syntax:
%_K32VER
This convenience function is equivalent to
@FILEVER[%_winsysdir\Kernel32.dll].
You can use it as an alternate way to get the Windows version.  The value will
be returned as four decimal values, separated by periods, without spaces or
leading zeroes. 
_USBDRIVES — Returns a list
of drives connected to USB ports. 
Syntax:
%_USBDRIVES
If more than one drive is returned, they will be separated with spaces.
for %drive in ( %_usbdrives ) do vol %_drive
Reference Information:
| Paging Options | Supported in several commands. | 
| Range Options | Supported in several commands. | 
| The Highlight Variable | Choose your colors. | 
| Startup Message | And how to suppress it. | 
| Changes | Slow march of progress, or just another bug hunt? | 
| Status and Licensing | 
Paging Options:
Many of the commands in this plugin have a /P option to page
output.  This option supports two suboptions: 
/P:time,lines
| time | time in seconds, or (with a trailing M) milliseconds | 
| lines | number of lines to display before pausing | 
Both time and lines are optional. The colon is not required, but you must use the comma if you want to specify lines.
rem  Scroll every ten seconds:
type /p:10 myfile.txt
rem  Display ten lines at a time:
type /p:,10 myfile.txt
rem  Display twenty lines at a time, and
rem    scroll every 2.5 seconds:
type /p:2500m,20
At the “Press a key to continue” prompt, most keys will advance by another screenful (or lines). But a few keys behave differently:
| A or C | turns off paging, and scrolls continuously | 
| Esc or Ctrl-C | aborts the current command | 
| / | scrolls half a screen, or half of lines | 
| 1 to 9 | scrolls that many lines, e.g. 3 scrolls three lines | 
Ranges:
This plugin supports the following range syntax:
Size range:  /[Ssmallest,largest]
You may omit either smallest or
largest.  You may qualify either with a trailing
letter:  lowercase k, m, g, etc.
to multiply by one thousand, one million, one billion, and so on; or
uppercase K, M, G, etc. to
multiply by 210, 220, 230, and so on.  If
largest begins with a + sign, it is
an increment over smallest.  Use
/![Ssmallest,largest]
to invert the test and return only files not in the given size range. 
Date range:  /[D[acw]:earliest,latest]
You may omit either earliest or latest; either defaults to the current date. The optional [acw] argument selects the date stamp to check. (If you want to check more than one date stamp, you must supply more than one date range option.) The colon after the [acw] is optional.
Dates may be given in the local date format, or in
yyyy-mm-dd
format (with a four-digit year).  You may also specify a date as an offset
preceded with a + or - sign; the offset is in days
relative to today’s date (for earliest) or
relative to earliest (in the case of
latest).  If earliest
turns out to be later than latest then the two
are exchanged. 
You may also give a specific time on either date, preceded
by an @ sign.  The time may be in either 24-hour format, or 12-hour
format with a trailing A or P. 
Use /![D[acw]:earliest,latest]
to invert the test and return only files not in the given date range. 
Time range:  /[T[acw]:earliest,latest]
You may omit either earliest or
latest.
The optional [acw]
argument selects the time stamp to check.  (If you want to check more than one
time stamp, you must supply more than one time range option.)  The colon after
the [acw]
is optional.  Times may be in either 24-hour format, or 12-hour format with a
trailing A or P. 
Use /![T[acw]:earliest,latest]
to invert the test and return only files not in the given time range. 
Exclusion range:  /[!wildspec]
Filenames matching the wildspec will be excluded. You can supply more than one wildspec by separating them with (unquoted) spaces.
Owner range:  /[Owildspec]
Files whose owners (in domain\user
format) do not match the wildspec will be
skipped.  Use /![Owildspec]
to invert the test and return only files which do not match the owner
wildspec. 
Description range:  /Iwildspec or (alternate syntax) /[Iwildspec]
If a file’s description does not match the wildspec,
it will be skipped.  Use /!Iwildspec
to invert the test, returning only files which do not match the description
wildspec. 
Day-of-the-week range:  /[W[acw]:days]
You may specify multiple days separated by commas, e.g.
/[W:MON,WED,FRI].  You can also give a range, for example
/[W:TUE-FRI].  WEEKENDS is accepted as a synonym for
SAT,SUN; WEEKDAYS is a synonym for MON-FRI.
The colon in this syntax is required. 
You may supply multiple ranges. A file must match all given ranges or it will be skipped.
Highlight Variable:
A few of the commands in this plugin feature highlighted output.  You can
customize this feature by setting an environment variable Highlight: 
rem  Disable highlight:
set highlight=none
rem  Set the highlight foreground:
set highlight=bright cyan
rem  Set both foreground and background:
set highlight=bri whi on blu
rem  Numbers are also supported:
set highlight=46
If the Highlight environment variable is not defined, the plugin will
check the registry for a value named Highlight of type REG_SZ.
The plugin will search, in this order: 
•  HKEY_CURRENT_USER\Software\JPPlugins\FileUtils | (affects this plugin only) | 
•  HKEY_CURRENT_USER\Software\JPPlugins | (affects several of my plugins) | 
Many commands also have a /D or /NC option to
disable highlighting. 
Startup Message:
This plugin displays an informational line when it initializes.  The
message will be suppressed in transient or pipe shells.  You can disable it
for all shells by defining an environment variable named NOLOADMSG,
for example:
set /e /u noloadmsg=1
Changes:
| Version: | Date: | Changes: | 
|---|---|---|
| 0.93.1.2 | 2025-10-09 | Fixed an issue with CFILES 
			sending ANSI sequences when the /? help text was redirected or piped.  | 
| 0.93.1.1 | 2025-09-29 | DATEDIR: 
			Added /Q to quote displayed filenames.  Now /T:F implies /T.  | 
| 0.93.1.0 | 2025-09-24 | Changes to DATEDIR
			to work with StrFTime.cpp 0.92.0.0.  | 
| 0.93.0.0 | 2025-09-22 | Added DATEDIR. FILEINFO:  Accepts /T:W as a synonym for /T:M, 
			for compatibility with DIR. CFILES:  Added /M: to include only files matching a
			given wildspec.  | 
| 0.92.1.2 | 2025-09-18 | Updated versions of conlist.cpp and mmfiles.cpp. | 
| 0.92.1.1 | 2025-08-22 | HEXDUMP: 
			/C: and /E: allow negative values to specify the starting/ending address 
			as an offset from the end of the file. /C: /E: and /M: now can combine a multiplier with a word
			size, e.g. /C:10KW for 10 kilowords = 20,480 bytes.  | 
| 0.92.1.0 | 2025-08-11 | BSPLIT:  Improved
			the help text slightly, and added /F? to list the supported extension numbering formats. Preliminary support for very long filenames (VLFNs).  | 
| 0.92.0.0 | 2025-08-08 | FILEINFO:  
			DisplayFileAttributes() also attempts to get and display the file’s owner. Preliminary support for very long filenames (VLFNs). DisplayFileVerHeader() can also pick up TTF font file info. HEXDUMP:  Returns ERROR_INVALID_PARAMETER if no
			arguments are passed.  (Can’t happen?) VLFN display tweak: If the filename has the \\?\ prefix, don’t display that 
			prefix in the filename header. EMPTIES:  Tweaks to better handle very long filenames. CFILES:  Added /L to show a legend at the end
			(for use with /C). Tweaks for very long filenames. DIRCMP:  Tweaks to better handle very long filenames. @DIRREADABLE, @DIRWRITABLE, 
			@NEWEST, @RANDFILE:
			Tweaks to better handle very long filenames.  | 
| 0.91.6.0 | 2025-08-01 | FILEINFO:  Now shows 
			TTF font info; /OF to disable. Added new functions @TTFCOUNT and @TTFINFO 
			to extract string info from .TTF files.  | 
| 0.91.5.2 | 2025-07-07 | HEXDUMP:  More 
			minor tweaks to the /I summary line:  pluralizes byte/bytes; if WordLen > 1, shows the word size 
			and word count; removed the hexadecimal file size.  | 
| 0.91.5.1 | 2025-06-30 | HEXDUMP:  In the
			/I summary line, CLIP: and - were not being handled nicely; fixed. In the /H and /HH header line, use fancy Unicode quotes around the filename of
			an actual file, as /I does. Removed hardcoded \r\n from header and summary lines; now they respect /LF and
			/CR. Added /NQ to suppress the fancy Unicode quote marks.  | 
| 0.91.5.0 | 2025-06-27 | CFILES:  /K
			now shows difference counts as well.  Documented /K.  | 
| 0.91.4.0 | 2025-06-27 | FILEINFO:  Now shows 
			NTFS streams info;  /ON to disable.  | 
| 0.91.3.0 | 2025-06-17 | HEXDUMP:  Added
			/BOM to replace any Byte Order Marks with the generic currency symbol.  Fixed an issue where an error
			in /ML: would exit without proper cleanup.  | 
| 0.91.2.3 | 2025-06-13 | HEXDUMP:  Fixes
			to the handling of control pictures:  Use the user’s specified replacement character if no control
			picture is available; use the correct control pic for DEL.  | 
| 0.91.2.0 | 2025-06-11 | HEXDUMP:  Added
			/ML: to set a maximum number of lines to dump.  | 
| 0.91.1.5 | 2025-05-07 | Added support for the
			NO_COLOR environment variable.  If
			NO_COLOR is defined and HIGHLIGHT is not, disable highlighting as if
			/D had been specified. HEXDUMP:  When dumping a UTF-8 text file as bytes, show dashes between
			bytes of a valid character.  Added /N8 to disable.  | 
| 0.91.1.3 | 2025-04-22 | FILEINFO: 
			DisplayLnkTarget() also shows executable info for .scr and 
			.dll files.  | 
| 0.91.1.2 | 2025-04-17 | FILEINFO:  When
			a .lnk points to an .exe, also show the executable
			type and the FileDescription string if available.  If there is a FileVersion string, display that in preference
			to the binary file version.  | 
| 0.91.1.1 | 2025-04-09 | FILEINFO:  When
			displaying the target of a .lnk file, also attempt to display version info for
			the target executable, if any.  | 
| 0.91.1.0 | 2025-04-04 | Added @NEWEST.  | 
| 0.91.0.0 | 2025-04-03 | Added CFILES.  Added 
			/TF to FILEINFO.  | 
| 0.90.0.8 | 2025-03-29 | FILEINFO:  When
			displaying the target of a .lnk file, if the target is an .exe
			file with a size of zero, check for an AppX alias and show that too if found. Added quotes around AppX alias targets.  | 
| 0.90.0.7 | 2025-03-27 | FILEINFO:   Added
			some more text file types:  .bat .btm .cmd .css .csv .h .htm .ini .xml. Minor code tweaks.  | 
| 0.90.0.6 | 2025-03-25 | FILEINFO:  For
			text file types, also display the line count and EOL type.  | 
| 0.90.0.5 | 2025-03-20 | HEXDUMP:
			Fixed incorrect buffer length in ShowFilenameHeader().  | 
| 0.90.0.4 | 2025-03-17 | HEXDUMP changes:
			Added /X to use control pictures for ASCII control characters. Fixed an issue which caused the text field to be lost if the final line overlapped the end of the buffer. Slightly simplified the ‘print word values’ loop.  | 
| 0.90.0.3 | 2025-01-10 | HEXDUMP:  Added
			/F?.  Added /F:+ and /F:- as synonyms for /F:S.  | 
| 0.90.0.2 | 2025-01-09 | FH_QueryTrueNameQuietly() no longer
			breaks filenames at semicolons.  | 
| 0.90.0.1 | 2025-01-06 | FILEINFO change: 
			If the file’s Open command is just “%1”, don’t bother to display it.  | 
| 0.90.0.0 | 2025-01-01 | Adds HEXDUMP.  | 
| 0.39.6.6 | 2025-01-01 | FILEINFO now 
			displays file type info; /OR to disable.  | 
| 0.39.6.5 | 2024-12-05 | FILEINFO change:
			DisplayAppXTarget() also chases symlinks as well as AppX aliases (accidental feature).  So roll 
			with it!  When following a symlink to an executable, prefix the symlink target with “Symlink”
			instead of “AppX alias”.  | 
| 0.39.6.4 | 2024-12-03 | FILEINFO: 
			The numeric file version is now displayed as “Version (binary)” to distinguish it from the version
			info strings.  | 
Status and Licensing:
Consider this beta software. It may well have issues. Try it at your own risk. If you find a problem, you can report it in the JP Software support forum.
FileUtils is currently licensed only for testing purposes. I may make binaries and source code available under some free license once I consider it ready for use.
Download:
You can download the current version of the plugin from https://charlesdye.net/dl/fileutils.zip.