The old, venerable Windows cmd
command prompt is always on hand for quick and dirty tasks. Today, we'll use it to copy files around.
If you can specify the files you want to copy with a simple mask, you have plenty of built-in support.
The copy command is your basic tool to copy files around.
The xcopy command adds the ability to copy subdirectories recursively.
Finally, robocopy is the supercharged file copier. Yes it handles subdirectories, but it allows customizing file and security attributes, restartable network mode, and some basic options for synchronization.
Sometimes, however, we have a very specific set of files to work with and checking things by hand comes in handy.
So, let's say we want to copy a handful of .dlls from under a directory tree. We can get a basic list of files like so.
dir /s /b the-directory\*.dll > %temp%\files.txt
The flags we're using are /s
to recurse in subdirectories, \b
for bare full-path filenames, and the *dll
mask will apply at every recursed directory.
We pipe that to a temporary file, and now we can review manually.
For extra bonus, we'll allow ourselves to delete some of the files, or add comments prefixed with #
- as is tradition.
Now, let's turn to our very powerful but syntactically tricky friend, for.
Let's look at some of the highlights in the documentation that will help us.
FOR /F ["options"] %variable IN (file-set) DO command [command-parameters]
file-set is one or more file names. Each file is opened, read
and processed before going on to the next file in file-set.
Processing consists of reading in the file, breaking it up into
individual lines of text and then parsing each line into zero or
more tokens. The body of the for loop is then called with the
variable value(s) set to the found token string(s). By default, /F
passes the first blank separated token from each line of each file.
Blank lines are skipped. You can override the default parsing
behavior by specifying the optional "options" parameter. This
is a quoted string which contains one or more keywords to specify
different parsing options. The keywords are:
eol=c - specifies an end of line comment character
(just one)
skip=n - specifies the number of lines to skip at the
beginning of the file.
delims=xxx - specifies a delimiter set. This replaces the
default delimiter set of space and tab.
tokens=x,y,m-n - specifies which tokens from each line are to
be passed to the for body for each iteration.
This will cause additional variable names to
be allocated. The m-n form is a range,
specifying the mth through the nth tokens. If
the last character in the tokens= string is an
asterisk, then an additional variable is
allocated and receives the remaining text on
the line after the last token parsed.
Based on this, here are the options we'd like to use:
/F
with the file-set option to read lines from the fileeol
can help us have comments in our lines (or comment out whole lines)rem print out the commands we're going to run
@FOR /F "eol=#" %i IN (%temp%\files.txt) DO @echo copy /y %i %copy_target%
rem now run them for real
@FOR /F "eol=#" %i IN (%temp%\files.txt) DO copy /y %i %copy_target%
skip
would be useful for a header in a tab separate file, but we don't need it here.
tokens
would also be handy to either read "all other text" or to pick specific values from a file.
Happy file copying!
Tags: shell