When you want to copy a file into a folder, make sure you have a folder


This story is inspired by an actual customer problem.

The program LitWare.exe is used for TPS management, and when you want to create a new TPS report, you have to pick a cover sheet. The program shows you the cover sheets that have been defined, which it loads from the C:\TPS Cover Sheets directory.

The customer found that on one of the machines, the cover sheets weren't showing up, even though the standard system setup copies a sample cover sheet into the C:\TPS Cover Sheets directory. The error message they got was Cannot load cover sheets. The directory name is invalid.

The customer did some troubleshooting and determined that "The cover sheet directory is missing, and we have a file instead."

C:\>dir
 Volume in drive C is INITECH
 Volume Serial Number is BAAD-F00D

 Directory of C:\

09/18/2006  02:43 PM                24 autoexec.bat
09/18/2006  02:43 PM                10 config.sys
03/18/2009  10:30 AM    <DIR>          Program Files
11/21/2008  01:04 PM             1,677 TPS Cover Sheets
02/20/2008  10:39 AM    <DIR>          Users
05/29/2009  02:23 PM    <DIR>          Windows
               2 File(s)          1,711 bytes
               3 Dir(s)  229,031,751,680 bytes free

One of my colleagues employed psychic powers to determine that at the time the customer tried to install the sample cover sheet on the machine, the C:\TPS Cover Sheets directory did not yet exist, and that the batch file they used to set up a new computer just does a copy \\server\TPSConfig\Sample.tps "C:\TPS Cover Sheets", which results in a file being created with the name C:\TPS Cover Sheets.

The customer was surprised by this conclusion. "I would think that copy will fail if the C:\TPS Cover Sheets directory doesn't exist, but this might be our problem. We'll look into it." (I guess this customer never used the copy command to copy a file to a new name.)

If the destination of a copy command exists and is a directory, then the source files are copied into that directory. If the destination of a copy command does not exists or if it exists and is a file, then the destination is treated as a file name for the destination. (If there is more than one source file, then they are concatenated as if they were text files.)

The customer went back and checked the scripts, and the line they used was almost exactly what my colleague predicted:

copy "\\INITECH\Defaults\Sample cover sheet.tps" "C:\TPS Cover Sheets" /Y

If the C:\TPS Cover Sheets directory hasn't been created yet, then that would explain the behavior they're seeing: The copy command sees that the destination doesn't exist and assumes you are doing a file-to-file copy (as opposed to a file-to-directory copy). In this case, the problem was that copying a sample cover sheet was a step they added to their setup scripts, but they added it before the step that creates the cover sheet directory. Reordering the two steps fixed the problem.

Comments (19)
  1. Gaspar says:

    “The customer found that on one of the machines, no of the cover sheets were showing up, even though the standard system setup copies a sample cover sheet into the C:TPS Cover Sheets directory. “

    I assume that it should read “…on one of the machines, <i>none</i> of the cover sheets…?”

    [Or something equally grammatical, yeah. Fixed, thanks. -Raymond]
  2. strik says:

    That’s why I would use xcopy instead:

    xcopy "\INITECHDefaultsSample cover sheet.tps" "C:TPS Cover Sheets" /Y

  3. John says:

    PC LOAD LETTER?  WTF does that mean?

  4. oliver says:

    Wouldn’t this error have been detected if they had appended a backslash to the target name? Like this:

    copy "\INITECHDefaultsSample cover sheet.tps" "C:TPS Cover Sheets" /Y

    I suppose the copy command would then fail with a "directory does not exist" error or similar?

  5. Alex says:

    Ha, TPS Reports :)

    "Office space".

  6. Dan says:

    Or:

    if not exist "C:TPS Cover Sheets" mkdir "C:TPS Cover Sheets"

    copy "\INITECHDefaultsSample cover sheet.tps" "C:TPS Cover Sheets" /Y

    IIRC if not exist works all the way back to MS-DOS 6 (except of course it can’t handle long file names).

  7. Dan says:

    Oh and I would use the backslash at the end too to imply the same destination file name, but assuming strik is right about the backslash thing I think my version would still be acceptable. :)

  8. dalek says:

    I frequently use a line like

    if not exist "C:TPS Cover Sheets" md "C:TPS Cover Sheets"

    in batch files to <i>try</i> to make sure a directory exists. However if they don’t know how the copy command works, they probably don’t know about if (not) exist either :)

  9. Miral says:

    I used to use "if not exist C:somedirnul md C:somedir", since I remember there being a problem with using the bare directory name in DOS (5/6, I think, maybe even Win95) — they reported that it didn’t exist because they were checking for file existence and it was a directory rather than a file.  But "nul" was a magic file that always existed in every directory, so this got around the problem.

    Sadly this doesn’t work in NT; "nul" is considered to never exist, so it will always try to create the directory even if it’s already there.  (Basically the opposite problem.)  But fortunately now the direct comparison works.

  10. porter says:

    I’ve noticed that mkdir now acts like the POSIX "mkdir -p dir", when did this change?

  11. strik says:

    @Oliver:

    At least until XP, copy cannot handle it if there is a backslash at the end of the destination. That’s why I suggested xcopy (if you look at the command line: *with* the backslash at the end), which handles this case.

  12. Gabe says:

    I would just always execute the mkdir command. If the directory doesn’t exist, it will create it, otherwise it will print an error which will be ignored because it’s running unattended in a batch file.

  13. Ian Argent says:

    Wouldn’t copy "\INITECHDefaultsSample cover sheet.tps" "C:TPS Cover Sheets." /Y have worked?

    (N/M – that won’t create the non-existant directory, will it?)

  14. Neil says:

    @porter

    mkdir /?

    That wasn’t so hard, was it?

  15. Teo says:

    Well, one can use JPSoft’s TCC cmd replacement. Its version of built-in "copy" has 28 switches, works with (S)ftp, has exclusion lists, and when combined with another built-in "select", has interactive mode where you choose what file to copy. Not to mention the TAB completion which works with hidden files, ***named streams*** (eat THAT, PowerShell) and does not kills the rest of the command line after the token you try to auto-complete.

    Btw, recently I tried to implement a recently fast copy algorithm, and boy, it is hard. I am on the verge of thinking it is *impossible*

  16. porter says:

    > That wasn’t so hard, was it?

    Except it didn’t answer the question.

    NT4SP6,WIN2K,XP all do the complete path. DOS and OS2WARP don’t, so when did mkdir start making the complete path?

  17. Coleman says:

    @Teo,

    one can use JPSoft’s TCC cmd replacement

    Except now they have to make sure this "cmd replacement" is installed on every PC where this script is run, so now they have 2 problems.

  18. James Schend says:

    You guys don’t have to keep offering solutions to the problem. Microsoft already solved it, that’s why it’s here on this blog.

  19. Scott says:

    Reminds me of an obscure similar problem I ran into back in the Win98 days. I was trying to install a program (cygwin, might have been), and I’d consistently get a failure when trying to create the file named "cdrom". After days of trying to figure out why I couldn’t create a file named "cdrom" anywhere, I realized I had real mode cdrom drivers installed, and had called the device "cdrom". Thus the setup program was tripping over the reserved device name. It’s always stuck in my mind as an example of what happens when users know a little too much for their own good ;)

Comments are closed.

Skip to main content