OK, I know what the actual problem is now. On Windows, && binds more tightly than IF does. So the PRE_LINK command in the first post is interpreted as
IF NOT EXIST c:\build-dir\Debug\data
( mkdir c:\build-dir\Debug\data && cp -auv C:/source-dir/data/* C:/build-dir/Debug/data )
which I would have said as one COMMAND if that is what I intended. By using two separate COMMANDs, I was stating my intention to be
( IF NOT EXIST c:\build-dir\Debug\data mkdir c:\build-dir\Debug\data )
&& ( cp -auv C:/source-dir/data/* C:/build-dir/Debug/data )
Would it be possible to get the Ninja generator for Windows to add parentheses to group things so such ambiguity doesn’t happen? Now that I know that the lack of parentheses is the problem, I can work around this myself, but I would like to help other people avoid pitfalls.