Batch, file copy and drag and drop bug - batch-file

I've been looking around for an answer to this and nothing I found could actually solve my problem - sorry if there is already an answered post similar to this one that I didn't find.
Chapter 1)
I have a batch file that is supposed to copy any file/folder (recursively) to a specific folder in my USB flash drive. So, I wrote this:
echo Copying files...
xcopy /s /i %1 \folder\Subfolder\%1
This turns out swell if I call the batch file from the command line, but it stops working if I drag the object (file/folder) onto the .bat itself. I'm sure the shell must return an error message, but I can't read it, since the command line window closes instantaneously (that's why I ran it from the command line) as usual.
Can you help me fixing this?
Chapter 2)
I'd like the batch file to be able to distinguish from two situations:
a) Copying the file "C:\Document.doc" to "\folder\Subfolder"
b) Copying the file "C:\SomeFolder" to \folder\Subfolder\SomeFolder"
My code already does b), it just doesn't distinguish from a) and when I try to copy a single file what it does is this:
the instruction
xcopy /s /i %1 \Folder\SubFolder\%1
becomes
xcopy /s /i C:\Document.doc \Folder\SubFolder\C:\Document.doc
instead of
xcopy /s /i C:\Document.doc \Folder\SubFolder\Document.doc
How can I make the batch able to correct this?
Thanks in advance!

%1 has the absolute path of the file, so when you drag a file you are telling the CMD to do this:
xcopy /S /i "C:\complete path of file\file.ext" "\folder\Subfolder\C:\complete path of file\file.ext"
You need to use the argument parameters to get the desired thing (absolute path, filename, extension, size of file, what you want)
like this:
xcopy /s /i "%~1" "\folder\Subfolder\%~nx1"
The example does:
xcopy /S /i "C:\complete path of file\file.ext" "\folder\Subfolder\filename.ext"
But really you don't need to use the second argument, you can simplify as this:
xcopy /s /i "%~1" "\folder\Subfolder\"
Because the destiny filename by default takes the same name of the original file.

Related

how to zip all files individually in all subfolders and remove original file after

what im looking for is a .bat file code to zip files individually in all subfolders in the current folder and then delete the of files after, to exclude already zipped/compressed files, what i dont want is folders to be zipped and i want the files to keep there name when zipped
i have a bunch of folders/files and the only code i found
#ECHO OFF
FOR %%i IN (*.*) DO (
ECHO "%%i" | FIND /I "batch zip files.bat" 1>NUL) || (
"c:\Program Files\7-Zip\7z.exe" a -tzip "%%~ni.zip" "%%i"
if %ERRORLEVEL% == 0 del "%%i"
)
)
zips all files in the current directory and doesnt touch subfolders
i'd appreciate it if anyone can do this for me as i can save a ton of space with all files zipped
The first issue you have with your provided code is that your For loop is only parsing files in the current directory, there is no recursion into subdirectories. To parse files within the subdirectories, I'd advise that you use a For /F loop, with the Dir command using its /B and /S options. I would also advise that you include the attribute option, /A, which will include every item, then omit those which you're not interested in. For instance, it's unlikely that you want to zip the directories, hidden files, reparse points, or system files. You can do that by excluding those attributes, /A:-D-H-L-S. To learn more about the For command, and the Dir command, open a Command Prompt window, type for /?, and press the ENTER key. You can then do the same for the Dir command, i.e for /?. As you have not defined a working directory at the start of your script, it will run against every file and directory in whatever is current at the time you run it. Because your code has a line excluding a file named batch zip files.bat, I'm going to assume that is the name of your running script, and that your intention is to therefore run the script against everything in the tree rooted from the same location as the batch file itself. To ensure that is always the case, for safety, I've defined that directory as the current directory from the outset, using the CD command, CD /D "%~dp0". %0 is a special batch file argument reference to itself, to learn more about this please take a look at the output from both call /?. You can also learn about the CD command entering cd /?, in a Command Prompt window too. To also omit your batch file, as you don't want it to be zipped and deleted, I've piped the results from the Dir command through FindStr, printing only items which do not exactly match the case insensitive literal string %~f0 (expanding to the full path of the batch file itself). Additionally, I've piped those results through another findstr.exe command to omit any files already carrying a .zip extension, as there's no point in zipping files which already zip files. (Please note however, that for more robust code, you should really check that those are zip archives and not just files carrying a misleading extension). The results from those commands are then passed one by one to the Do portion which includes your 7z.exe command. I've assumed at this stage, that your intention was to save the zipped archives to the same location as the originating files. To do that I've used variable expansion on %%G to stipulate its directory, path, and name, %%~dpnG, (see the usage information under for /? to recap). Upon successful completion of the archiving process, the original file will be deleted, to do that I appended the -sdel option to your original command string. Please be aware that you may want to include additional options, should you wish to update existing zip files etc. (use "%ProgramFiles%\7-Zip\7z.exe" -? in a Command Prompt window to see them). As I've not mentioned it previously, at the beginning of the script, I made sure that extensions were enabled. Whilst it is the default option, it's safer to be sure, as variable expansion and the commands CD, and For can be affected, if they're not.
Here's the code as explained above:
#Echo Off
SetLocal EnableExtensions
CD /D "%~dp0"
For /F "EOL=? Delims=" %%G In ('Dir "*" /A:-D-H-L-S /B /S 2^> NUL ^|
%SystemRoot%\System32\findstr.exe /I /L /V /X "%~f0" ^|
%SystemRoot%\System32\findstr.exe /E /I /L /V ".zip"'
) Do "%ProgramFiles%\7-Zip\7z.exe" a -tzip "%%~dpnG.zip" "%%G" -sdel
Looking at your question, which has changed from what you'd asked initially, you appear to not be interested in the files of the batch file directory any more, "zip files individually in all subfolders in the current folder". For that reason, I've provided the following alternative, methodology.
The difference is that I first of all use a For loop to include only directories in the current working location, /A:D-H-L-S, before running the same method used in my previous example, but with one difference. As we're now no longer zipping files in the current working directory, we can remove the findstr.exe command filtering out the running batch file:
#Echo Off
SetLocal EnableExtensions
CD /D "%~dp0"
For /F "EOL=? Delims=" %%G In ('Dir "*" /A:D-H-L-S /B 2^> NUL'
) Do For /F "EOL=? Delims=" %%H In ('Dir "%%G" /A:-D-H-L-S /B /S 2^> NUL ^|
%SystemRoot%\System32\findstr.exe /E /I /L /V ".zip"'
) Do "%ProgramFiles%\7-Zip\7z.exe" a -tzip "%%~dpnH.zip" "%%H" -sdel
Please be aware, that my answers above are to essentially correct your code attempt, and not a personal recommendation for speed, or in performing the task laid out in your question. Additionally, I have no idea what will happen if any of those files are in use/locked, and have made no attempt at checking for such scenarios.

Test IF file exist, ELSE xcopy these two files

Morning all.
So I've been up hours trying to cobble together -a variety of replies to other posts- into my own code in order to see if I could get something usable. No-go. I'm sufficiently lost in the sauce that I've now got to ask for some help from you.
Background:
OS: Windows 10
I use the program text2folders.exe to create 20-30 new folders on a secondary drive every night.
Primarily, I have a base file "aGallery-dl.bat" that I populate each folder with using an xcopy batch file. Secondarily, from time to time I update the source file "aGallery-dl.bat" using the same xcopy and this overwrites the older target file, populating all folders with the newest "aGallery-dl.bat" (whether they need it or not). All is well.
#echo off
for /D %%a in ("U:\11Web\gallery-dl\deviantart\*.*") do xcopy /y /d ".\aGallery-dl.bat" "%%a\"
I've recently decided I want to add two new files to each folder and have expanded my xcopy to include these. All is well.
#echo off
for /D %%a in ("U:\11Web\gallery-dl\deviantart\*.*") do xcopy /y /d ".\aGallery-dl.bat" "%%a\"
for /D %%a in ("U:\11Web\gallery-dl\deviantart\*.*") do xcopy ".\Folder.jpg" "%%a\"
for /D %%a in ("U:\11Web\gallery-dl\deviantart\*.*") do xcopy ".\Folder2.jpg" "%%a\"
Folder.jpg
a big red X
Folder2.jpg
a big yellow ! mark
When I choose to run a "aGallery-dl.bat" in a given folder (again, one of 100's), it first deletes Folder.jpg then renames Folder2.jpg to Folder.jpg. This has the effect of the red X being replaced by the yellow ! when viewing the folder in File Explorer parent folder. Secondly, it calls "gallery-dl.exe." I use going from red to yellow to let me know I've run "aGallery-dl.bat" at least once. All is well.
rem #echo off
del .\Folder.jpg
ren .\Folder2.jpg Folder.jpg
FOR /F %%i IN ('cd') DO set FOLDER=%%~nxi
"C:\Program Files (x86)\gallery-dl\gallery-dl.exe" -d "U:\11Web\gallery-dl" --download-archive ".\aGDB.sqlite3" "https://www.deviantart.com/"%FOLDER%"/gallery/all"
del .\Folder.jpg
If "aGallery-dl.bat" completes successfully, it finally deletes the Folder.jpg (currently yellow !), and now the representative contents of the folder (usually DeviantArt .jpg's) are visible.
Problem:
When I have to re-run my original xcopy command to update "aGallery-dl.bat" in ALL FOLDERS, the Folder.jpg and Folder2.jpg will be re-copied to all folders, defeating the purpose of deleting them once via "aGallery-dl.bat." I don't want to have to go back and re-run "aGallery-dl.bat" intermittently across 100's of folders (again, only those that have had aGallery-dl.bat run at least once). I need some type of test, that if "aGallery-dl.bat" is already present in the target folder, DO NOT xcopy Folder.jpg and Folder2.jpg aka vague example, below.
*********************************Some sort of test statement here!!!***********************
:aGallery-dlPresent
GOTO eof
:aGallery-dlNotPresent
for /D %%a in ("U:\11Web\gallery-dl\deviantart\*.*") do xcopy ".\Folder.jpg" "%%a\"
for /D %%a in ("U:\11Web\gallery-dl\deviantart\*.*") do xcopy ".\Folder2.jpg" "%%a\"
GOTO eof
:eof
I had found a hopeful candidate test statement in the below (copied in its original form from what/where I read in other post), but am looking for ideas/replacements as I HAVE NO IDEA how to modify/inject/implement the below to work in the above.
If exist \\%DIR%\%Folder%\123456789.wav xcopy \\%DIR%\%Folder%\123456789.wav D:\%New Folder%\ /y
Having XCopy copy a file and not overwrite the previous one if it exists (without prompting)
Note: The below is a vague approximation of what it should all look like (barring having a correct -test statement-).
rem #echo off
*********************************Some sort of test statement here!!!***********************
:aGallery-dlPresent
GOTO eof
:aGallery-dlNotPresent
for /D %%a in ("U:\11Web\gallery-dl\deviantart\*.*") do xcopy ".\Folder.jpg" "%%a\"
for /D %%a in ("U:\11Web\gallery-dl\deviantart\*.*") do xcopy ".\Folder2.jpg" "%%a\"
GOTO eof
:eof
for /D %%a in ("U:\11Web\gallery-dl\deviantart\*.*") do xcopy /y /d ".\aGallery-dl.bat" "%%a\"
The command for copying a file is COPY. It is an internal command of Windows command processor cmd.exe. XCOPY is an eXtended file and directory copying executable in directory %SystemRoot%\System32 which is deprecated since Windows Vista as there is even more powerful ROBOCOPY which is with full qualified file name %SystemRoot%\System32\robocopy.exe.
There is no need to use XCOPY or ROBOCOPY for this simple file copying task. COPY is enough on source files aGallery-dl.bat, Folder.jpgand Folder2.jpg don't have hidden attribute set and the same files in the target directories don't have read-only attribute set.
.\ references the current directory which can be any directory. Windows Explorer sets the directory of the batch file as current directory on double clicking on a batch file. But this is nearly the only method to run a batch file on which the directory of the executed batch file is set automatically as current directory (except the batch file is stored on a network resource accessed using UNC path).
There is %~dp0 to reference the path of the batch file. This path always ends with a backslash which means that no additional backslash is needed on concatenating the batch file path with a file or folder name. The usage of %~dp0 makes it possible to reference files in same directory as the executed batch file independent on which directory is the current directory on execution of the batch file.
The batch file needed for your task is:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
for /D %%I in ("U:\11Web\gallery-dl\deviantart\*") do (
if not exist "%%I\aGallery-dl.bat" (
copy "%~dp0Folder.jpg" "%%I\"
copy "%~dp0Folder2.jpg" "%%I\"
)
copy /Y "%~dp0aGallery-dl.bat" "%%I\"
)
endlocal
A file/folder name must be enclosed in " if containing a space or one of these characters &()[]{}^=;!'+,`~. For that reason all file/folder names are enclosed in this batch file in double quotes although inside the batch files no file/folder name contains a space or one of the characters in the list. It is important to understand on batch file writing how a command line looks like after Windows command processor processed the command line. See following topics:
How does the Windows Command Interpreter (CMD.EXE) parse scripts?
How to debug a batch file?
Windows interprets *.* like just * which means any file or folder name. For that reason it is enough to just write * and omit .*.
Please note that for /D ignores directories with hidden attribute set.
The batch file checks first for each subfolder if it does not contain the batch file aGallery-dl.bat. In this case it copies the two files Folder.jpg and Folder2.jpg from directory of executed batch file to current subdirectory of U:\11Web\gallery-dl\deviantart.
Then the batch file aGallery-dl.bat is copied from directory of executed batch file to to current subdirectory of U:\11Web\gallery-dl\deviantart independent on its existence in the destination directory.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /? ... explains %~dp0 ... drive and path of argument 0 ... full batch file path.
cmd /? ... outputs the help of Windows command processor executing a batch file.
copy /?
echo /?
endlocal /?
for /?
if /?
setlocal /?
See also the chapters Issue 6 and Issue 7 in this answer why using setlocal EnableExtensions DisableDelayedExpansion and endlocal although not necessary by default and why using I instead of a as loop variable although a would work here, too.

XCOPY in a Batch Script - Avoid the File or Directory Prompt [duplicate]

I have a simple copy from-to script for one of my friends who is missing a file 20 km from my desk.
When testing the script out I am prompted if my file shapes.atc is a file or a folder.
I can tell you that its a file. How can I automatically copy it with my friend needs to just double click the batch to get the file copying job done.
xcopy /s/y J:\"My Name"\"FILES IN TRANSIT"\JOHN20101126\"Missing file"\Shapes.atc C:\"Documents and Settings"\"His name"\"Application Data"\Autodesk\"AutoCAD 2010"\"R18.0"\enu\Support\Shapes.atc
A seemingly undocumented trick is to put a * at the end of the destination - then xcopy will copy as a file, like so
xcopy c:\source\file.txt c:\destination\newfile.txt*
The echo f | xcopy ... trick does not work on localized versions of Windows, where the prompt is different.
Actually xcopy does not ask you if the original file exists, but if you want to put it in a new folder named Shapes.atc, or in the folder Support (which is what you want.
To prevent xcopy from asking this, just tell him the destination folder, so there's no ambiguity:
xcopy /s/y "J:\Old path\Shapes.atc" "C:\Documents and Settings\his name\Support"
If you want to change the filename in destination just use copy (which is more adapted than xcopy when copying files):
copy /y "J:\Old path\Shapes.atc" "C:\Documents and Settings\his name\Support\Shapes-new.atc
The real trick is: Use a Backslash at the end of the target path where to copy the file. The /Y is for overwriting existing files, if you want no warnings.
Example:
xcopy /Y "C:\file\from\here.txt" "C:\file\to\here\"
echo f | xcopy /s/y J:\"My Name"\"FILES IN TRANSIT"\JOHN20101126\"Missing file"\Shapes.atc C:\"Documents and Settings"\"His name"\"Application Data"\Autodesk\"AutoCAD 2010"\"R18.0"\enu\Support\Shapes.atc
Referencing XCopy Force File
For forcing files, we could use pipeline "echo F |":
C:\Trash>xcopy 23.txt 24.txt
Does 24.txt specify a file name
or directory name on the target
(F = file, D = directory)?
C:\Trash>echo F | xcopy 23.txt 24.txt
Does 24.txt specify a file name
or directory name on the target
(F = file, D = directory)? F
C:23.txt
1 File(s) copied
For forcing a folder, we could use /i parameter for xcopy or using a backslash() at the end of the destination folder.
The /i switch might be what your after.
From xcopy /?
/I If destination does not exist and copying more than one file,
assumes that destination must be a directory.
Well, for the task as asked by just me the perhaps best solution would be the following command according to the incomplete advice of Andy Morris:
xcopy "J:\My Name\FILES IN TRANSIT\JOHN20101126\Missing file\Shapes.atc" "C:\Documents and Settings\His name\Application Data\Autodesk\AutoCAD 2010\R18.0\enu\Support\" /Q /R /S /Y
This works for this simple file copying task because of
specifying just the destination directory instead of destination file and
ending destination directory with a backslash which is very important as otherwise XCOPY would even with /I prompt for file or directory on copying just a single file.
The other parameters not related to the question are:
/Q ... quiet
/Y ... yes (OS language independent) on overwrite existing file
/R ... overwrite also read-only, hidden and system file
/S ... from specified directory and all subdirectories.
Well, I don't know if /S is really needed here because it is unclear if just J:\My Name\FILES IN TRANSIT\JOHN20101126\Missing file\Shapes.atc should be copied or all Shapes.atc found anywhere in directory tree of J:\My Name\FILES IN TRANSIT\JOHN20101126\Missing file.
The explanation for the parameters can be read by opening a command prompt window and running from within this window xcopy /? to get output the help for XCOPY.
But none of the provided solutions worked for a file copying task on which a single file should be copied into same directory as source file, but with a different file name because of current date and time is inserted in file name before file extension.
The source file can have hidden or system attribute set which excludes the usage of COPY command.
The batch file for creating the time stamped file should work also on Windows XP which excludes ROBOCOPY because by default not available on Windows XP.
The batch file should work with any file including non typical files like .gitconfig or .htaccess which are files without a file extension starting with a point to hide them on *nix systems. Windows command processor interprets such files as files with no file name and having just a file extension because of the rule that everything after last point is the extension of the file and everything before last point is the file name.
For a complete task description and the final, fully commented solution see the post Create a backup copy of files in UltraEdit forum.
Patrick's, Interociter Operator's and CharlesB's solutions do not work because using /Y does not avoid the file or directory prompt if the destination file does not already exist.
Andy Morris' and grenix's solutions can't be used for the single file copying task as destination must be the name of destination file and not the name of destination directory. The destination directory is the same as the source directory, but name of destination file is different to name of source file.
DosMan's and Govert's solutions simply don't work for files starting with a point and not having a file extension.
For example the command
xcopy C:\Temp\.gitconfig C:\Temp\.gitconfig_2016-03-07_15-30-00* /C /H /K /Q /R /V /Y
results in following error message on execution:
English:  Could not expand second file name so as to match first.
German: Zweiter Dateiname konnte nicht so erweitert werden, dass er zum ersten passt.
And finally Denis Ivin's solution has the restriction that the operating system language dependent character for an automatic answering of the file OR directory prompt must be known.
So I thought about methods to get F for File on English Windows or D for Datei on German Windows or ? for ... on ... Windows automatically.
And it is indeed possible to determine the language dependent character for an automatic answering of the prompt.
A hack is used to get the language dependent letter from prompt text without really copying any file.
Command XCOPY is used to start copying the batch file itself to folder for temporary files with file extension being TMP for destination file. This results in a prompt by XCOPY if there is not already a file with that name in temporary files folder which is very unlikely.
The handler of device NUL is used as an input handler for XCOPY resulting in breaking the copying process after the prompt was output by XCOPY two times.
This output is processed in a FOR loop which is exited on first line starting with an opening parenthesis. This is the line on which second character defines the letter to use for specifying that destination is a file.
Here is a batch file using XCOPY with the code to determine the required letter for an automatic answering of the file or directory prompt to create a time stamped copy of a single file in same directory as the source file even if source file is a hidden or system file and even if the source file starts with a point and does not have a file extension.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Batch file must be started or called with name of a single file.
if "%~1" == "" exit /B
for /F "delims=*?" %%I in ("#%~1#") do if not "%%I" == "#%~1#" exit /B
if not exist "%~1" exit /B
if exist "%~1\" exit /B
rem Determine the character needed for answering prompt of
rem XCOPY for destination being a file and not a directory.
del /F "%TEMP%\%~n0.tmp" 2>nul
for /F %%I in ('%SystemRoot%\System32\xcopy.exe "%~f0" "%TEMP%\%~n0.tmp" ^<nul') do (
set "PromptAnswer=%%I"
setlocal EnableDelayedExpansion
if "!PromptAnswer:~0,1!" == "(" set "PromptAnswer=!PromptAnswer:~1,1!" & goto CopyFile
endlocal
)
echo ERROR: Failed to determine letter for answering prompt of XCOPY.
exit /B
:CopyFile
endlocal & set "PromptAnswer=%PromptAnswer%"
rem This is a workaround for files starting with a point and having no
rem file extension like many hidden files on *nix copied to Windows.
if "%~n1" == "" (
set "FileNameWithPath=%~dpx1"
set "FileExtension="
) else (
set "FileNameWithPath=%~dpn1"
set "FileExtension=%~x1"
)
rem Get local date and time in region and language independent format YYYYMMDDHHmmss
rem and reformat the local date and time to format YYYY-MM-DD_HH-mm-ss.
for /F "tokens=2 delims==." %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS get LocalDateTime /format:value') do set "LocalDateTime=%%I"
set "LocalDateTime=%LocalDateTime:~0,4%-%LocalDateTime:~4,2%-%LocalDateTime:~6,2%_%LocalDateTime:~8,2%-%LocalDateTime:~10,2%-%LocalDateTime:~12,2%"
rem Do the copy with showing what is copied and with printing success or
rem an error message if copying fails for example on sharing violation.
echo Copy "%~f1" to "%FileNameWithPath%_%LocalDateTime%%FileExtension%"
for /F %%I in ('echo %PromptAnswer% ^| %SystemRoot%\System32\xcopy.exe "%~f1" "%FileNameWithPath%_%LocalDateTime%%FileExtension%" /C /H /K /Q /R /V /Y') do set "FilesCopied=%%I"
if "%FilesCopied%" == "1" (echo Success) else echo ERROR: Copying failed, see error message above.
This batch code was tested on German Windows XP SP3 x86 and English Windows 7 SP1 x64.
See the post Create a backup copy of files in UltraEdit forum for a similar, fully commented batch file explaining all parts of the batch code.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
del /?
echo /?
exit /?
for /?
goto /?
if /?
rem /?
set /?
setlocal /?
wmic OS get /?
xcopy /?
Further the Microsoft article about Using command redirection operators should be read, too.
The trick of appending "*" can be made to work when the new extension is shorter. You need to pad the new extension with blanks, which can only be done by enclosing the destination file name in quotes. For example:
xcopy foo.shtml "foo.html *"
This will copy and rename without prompting.
"That's not a bug, it's a feature!" (I once saw a VW Beetle in the Microsoft parking lot with the vanity plate "FEATURE".) These semantics for rename go all the way back to when I wrote DOS v.1. Characters in the new name are substituted one by one for characters in the old name, unless a wildcard character (? or *) is present in the new name. Without adding the blank(s) to the new name, remaining characters are copied from the old name.
xcopy /s/y J:\"My Name"\"FILES IN TRANSIT"\JOHN20101126\"Missing file"\Shapes.atc C:\"Documents and Settings"\"His name"\"Application Data"\Autodesk\"AutoCAD 2010"\"R18.0"\enu\Support\*.*"
..should do it.
Good idea to do an:
IF NOT EXIST "C:\Documents and Settings\His name\Application Data\Autodesk\AutoCAD 2010\R18.0\enu\Support\Shapes.atc" ECHO/ && ECHO/ && ECHO * * * * * COPY FAILED - Call JustME at 555-555-1212 && ECHO/ && pause
(assuming you've done a rename of previous version to .old)
XCOPY /Z <----- restartable mode - good for large files.
The virtual parent trick
Assuming you have your source and destination file in
%SRC_FILENAME% and %DST_FILENAME%
you could use a 2 step method:
#REM on my win 7 system mkdir creates all parent directories also
mkdir "%DST_FILENAME%\.."
xcopy "%SRC_FILENAME% "%DST_FILENAME%\.."
this would be resolved to e.g
mkdir "c:\destination\b\c\file.txt\.."
#REM The special trick here is that mkdir can create the parent
#REM directory of a "virtual" directory (c:\destination\b\c\file.txt\) that
#REM doesn't even need to exist.
#REM So the directory "c:\destination\b\c" is created here.
#REM mkdir "c:\destination\b\c\dummystring\.." would have the same effect
xcopy "c:\source\b\c\file.txt" "c:\destination\b\c\file.txt\.."
#REM xcopy computes the real location of "c:\destination\b\c\file.txt\.."
#REM which is the now existing directory "c:\destination\b\c"
#REM (the parent directory of the "virtual" directory c:\destination\b\c\file.txt\).
I came to the idea when I stumbled over some really wild ../..-constructs in the command lines generated from a build process.
I had exactly the same problem, where is wanted to copy a file into an external hard drive for backup purposes.
If I wanted to copy a complete folder, then COPY was quite happy to create the destination folder and populate it with all the files.
However, I wanted to copy a file once a day and add today's date to the file.
COPY was happy to copy the file and rename it in the new format, but only as long as the destination folder already existed.
my copy command looked like this:
COPY C:\SRCFOLDER\MYFILE.doc D:\DESTFOLDER\MYFILE_YYYYMMDD.doc
Like you, I looked around for alternative switches or other copy type commands, but nothing really worked like I wanted it to.
Then I thought about splitting out the two different requirements by simply adding a make directory ( MD or MKDIR ) command before the copy command.
So now i have
MKDIR D:\DESTFOLDER
COPY C:\SRCFOLDER\MYFILE.doc D:\DESTFOLDER\MYFILE_YYYYMMDD.doc
If the destination folder does NOT exist, then it creates it.
If the destination folder DOES exist, then it generates an error message.. BUT, this does not stop the batch file from continuing on to the copy command.
The error message says:
A subdirectory or file D:\DESTFOLDER already exists
As i said, the error message doesn't stop the batch file working and it is a really simple fix to the problem.
Hope that this helps.

CMD "MOVE /Y" asks for confirmation

I'm still working on getting this: CMD for unable to move files due to string butchering to work.
My batch script looks like this right now,
FOR /F "delims=" %%T IN ('dir G:\ /B /A:D') DO (
CD "G:\%%T"
FOR /R %%D IN (*) DO (MOVE /Y "%%D" "G:\%%T")
)
PAUSE
and does as I intended, however as soon as it finds a duplicate file, it asks what it's supposed to do (overwrite: yes/no/all) for EACH file. Ordering to replace ALL only replaces one file.
Image: http://imgur.com/aKLsKs1
Why does it do that, and how do I fix it?
EDIT:
Turns out to be a windows bug of sorts. ROBOCOPY or XCOPY both work and their quiet switches work.
As you said, Robocopy does what you need and it smart about doing it.
http://social.technet.microsoft.com/wiki/contents/articles/1073.robocopy-and-a-few-examples.aspx
since windows 2000, the behaviour of the command is to prompt for confirmation regardless of the /y switch, unless the command is triggered from a script.
you can override this by setting the environment variable COPYCMD to /Y before running your move command. eg: SET COPYCMD=/Y && move /Y a b
this behaviour is documented at: https://ss64.com/nt/move.html
Funny bc.
/y : Suppresses prompting to confirm you want to overwrite an existing destination file.
/-y : Causes prompting to confirm you want to overwrite an existing destination file.
Have u tried a little /y ?
Strange thing...
move /? says (translated, because my help is german):
you have to confirm overwriting by default, in spite you call it from a batch file.
I just tried this very simple batchfile:
move test.txt test
test.txt is moved into folder test and the existing file is overwritten without confirmation.
When I give this command at the prompt (not batchfile), it asks for overwriting (as designed)
So all you have to do is removing /Y (strange, but fact)
(using Win7 - if this matters)

Why does the command XCOPY in batch file ask for file or folder?

I have a simple copy from-to script for one of my friends who is missing a file 20 km from my desk.
When testing the script out I am prompted if my file shapes.atc is a file or a folder.
I can tell you that its a file. How can I automatically copy it with my friend needs to just double click the batch to get the file copying job done.
xcopy /s/y J:\"My Name"\"FILES IN TRANSIT"\JOHN20101126\"Missing file"\Shapes.atc C:\"Documents and Settings"\"His name"\"Application Data"\Autodesk\"AutoCAD 2010"\"R18.0"\enu\Support\Shapes.atc
A seemingly undocumented trick is to put a * at the end of the destination - then xcopy will copy as a file, like so
xcopy c:\source\file.txt c:\destination\newfile.txt*
The echo f | xcopy ... trick does not work on localized versions of Windows, where the prompt is different.
Actually xcopy does not ask you if the original file exists, but if you want to put it in a new folder named Shapes.atc, or in the folder Support (which is what you want.
To prevent xcopy from asking this, just tell him the destination folder, so there's no ambiguity:
xcopy /s/y "J:\Old path\Shapes.atc" "C:\Documents and Settings\his name\Support"
If you want to change the filename in destination just use copy (which is more adapted than xcopy when copying files):
copy /y "J:\Old path\Shapes.atc" "C:\Documents and Settings\his name\Support\Shapes-new.atc
The real trick is: Use a Backslash at the end of the target path where to copy the file. The /Y is for overwriting existing files, if you want no warnings.
Example:
xcopy /Y "C:\file\from\here.txt" "C:\file\to\here\"
echo f | xcopy /s/y J:\"My Name"\"FILES IN TRANSIT"\JOHN20101126\"Missing file"\Shapes.atc C:\"Documents and Settings"\"His name"\"Application Data"\Autodesk\"AutoCAD 2010"\"R18.0"\enu\Support\Shapes.atc
Referencing XCopy Force File
For forcing files, we could use pipeline "echo F |":
C:\Trash>xcopy 23.txt 24.txt
Does 24.txt specify a file name
or directory name on the target
(F = file, D = directory)?
C:\Trash>echo F | xcopy 23.txt 24.txt
Does 24.txt specify a file name
or directory name on the target
(F = file, D = directory)? F
C:23.txt
1 File(s) copied
For forcing a folder, we could use /i parameter for xcopy or using a backslash() at the end of the destination folder.
The /i switch might be what your after.
From xcopy /?
/I If destination does not exist and copying more than one file,
assumes that destination must be a directory.
Well, for the task as asked by just me the perhaps best solution would be the following command according to the incomplete advice of Andy Morris:
xcopy "J:\My Name\FILES IN TRANSIT\JOHN20101126\Missing file\Shapes.atc" "C:\Documents and Settings\His name\Application Data\Autodesk\AutoCAD 2010\R18.0\enu\Support\" /Q /R /S /Y
This works for this simple file copying task because of
specifying just the destination directory instead of destination file and
ending destination directory with a backslash which is very important as otherwise XCOPY would even with /I prompt for file or directory on copying just a single file.
The other parameters not related to the question are:
/Q ... quiet
/Y ... yes (OS language independent) on overwrite existing file
/R ... overwrite also read-only, hidden and system file
/S ... from specified directory and all subdirectories.
Well, I don't know if /S is really needed here because it is unclear if just J:\My Name\FILES IN TRANSIT\JOHN20101126\Missing file\Shapes.atc should be copied or all Shapes.atc found anywhere in directory tree of J:\My Name\FILES IN TRANSIT\JOHN20101126\Missing file.
The explanation for the parameters can be read by opening a command prompt window and running from within this window xcopy /? to get output the help for XCOPY.
But none of the provided solutions worked for a file copying task on which a single file should be copied into same directory as source file, but with a different file name because of current date and time is inserted in file name before file extension.
The source file can have hidden or system attribute set which excludes the usage of COPY command.
The batch file for creating the time stamped file should work also on Windows XP which excludes ROBOCOPY because by default not available on Windows XP.
The batch file should work with any file including non typical files like .gitconfig or .htaccess which are files without a file extension starting with a point to hide them on *nix systems. Windows command processor interprets such files as files with no file name and having just a file extension because of the rule that everything after last point is the extension of the file and everything before last point is the file name.
For a complete task description and the final, fully commented solution see the post Create a backup copy of files in UltraEdit forum.
Patrick's, Interociter Operator's and CharlesB's solutions do not work because using /Y does not avoid the file or directory prompt if the destination file does not already exist.
Andy Morris' and grenix's solutions can't be used for the single file copying task as destination must be the name of destination file and not the name of destination directory. The destination directory is the same as the source directory, but name of destination file is different to name of source file.
DosMan's and Govert's solutions simply don't work for files starting with a point and not having a file extension.
For example the command
xcopy C:\Temp\.gitconfig C:\Temp\.gitconfig_2016-03-07_15-30-00* /C /H /K /Q /R /V /Y
results in following error message on execution:
English:  Could not expand second file name so as to match first.
German: Zweiter Dateiname konnte nicht so erweitert werden, dass er zum ersten passt.
And finally Denis Ivin's solution has the restriction that the operating system language dependent character for an automatic answering of the file OR directory prompt must be known.
So I thought about methods to get F for File on English Windows or D for Datei on German Windows or ? for ... on ... Windows automatically.
And it is indeed possible to determine the language dependent character for an automatic answering of the prompt.
A hack is used to get the language dependent letter from prompt text without really copying any file.
Command XCOPY is used to start copying the batch file itself to folder for temporary files with file extension being TMP for destination file. This results in a prompt by XCOPY if there is not already a file with that name in temporary files folder which is very unlikely.
The handler of device NUL is used as an input handler for XCOPY resulting in breaking the copying process after the prompt was output by XCOPY two times.
This output is processed in a FOR loop which is exited on first line starting with an opening parenthesis. This is the line on which second character defines the letter to use for specifying that destination is a file.
Here is a batch file using XCOPY with the code to determine the required letter for an automatic answering of the file or directory prompt to create a time stamped copy of a single file in same directory as the source file even if source file is a hidden or system file and even if the source file starts with a point and does not have a file extension.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Batch file must be started or called with name of a single file.
if "%~1" == "" exit /B
for /F "delims=*?" %%I in ("#%~1#") do if not "%%I" == "#%~1#" exit /B
if not exist "%~1" exit /B
if exist "%~1\" exit /B
rem Determine the character needed for answering prompt of
rem XCOPY for destination being a file and not a directory.
del /F "%TEMP%\%~n0.tmp" 2>nul
for /F %%I in ('%SystemRoot%\System32\xcopy.exe "%~f0" "%TEMP%\%~n0.tmp" ^<nul') do (
set "PromptAnswer=%%I"
setlocal EnableDelayedExpansion
if "!PromptAnswer:~0,1!" == "(" set "PromptAnswer=!PromptAnswer:~1,1!" & goto CopyFile
endlocal
)
echo ERROR: Failed to determine letter for answering prompt of XCOPY.
exit /B
:CopyFile
endlocal & set "PromptAnswer=%PromptAnswer%"
rem This is a workaround for files starting with a point and having no
rem file extension like many hidden files on *nix copied to Windows.
if "%~n1" == "" (
set "FileNameWithPath=%~dpx1"
set "FileExtension="
) else (
set "FileNameWithPath=%~dpn1"
set "FileExtension=%~x1"
)
rem Get local date and time in region and language independent format YYYYMMDDHHmmss
rem and reformat the local date and time to format YYYY-MM-DD_HH-mm-ss.
for /F "tokens=2 delims==." %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS get LocalDateTime /format:value') do set "LocalDateTime=%%I"
set "LocalDateTime=%LocalDateTime:~0,4%-%LocalDateTime:~4,2%-%LocalDateTime:~6,2%_%LocalDateTime:~8,2%-%LocalDateTime:~10,2%-%LocalDateTime:~12,2%"
rem Do the copy with showing what is copied and with printing success or
rem an error message if copying fails for example on sharing violation.
echo Copy "%~f1" to "%FileNameWithPath%_%LocalDateTime%%FileExtension%"
for /F %%I in ('echo %PromptAnswer% ^| %SystemRoot%\System32\xcopy.exe "%~f1" "%FileNameWithPath%_%LocalDateTime%%FileExtension%" /C /H /K /Q /R /V /Y') do set "FilesCopied=%%I"
if "%FilesCopied%" == "1" (echo Success) else echo ERROR: Copying failed, see error message above.
This batch code was tested on German Windows XP SP3 x86 and English Windows 7 SP1 x64.
See the post Create a backup copy of files in UltraEdit forum for a similar, fully commented batch file explaining all parts of the batch code.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
del /?
echo /?
exit /?
for /?
goto /?
if /?
rem /?
set /?
setlocal /?
wmic OS get /?
xcopy /?
Further the Microsoft article about Using command redirection operators should be read, too.
The trick of appending "*" can be made to work when the new extension is shorter. You need to pad the new extension with blanks, which can only be done by enclosing the destination file name in quotes. For example:
xcopy foo.shtml "foo.html *"
This will copy and rename without prompting.
"That's not a bug, it's a feature!" (I once saw a VW Beetle in the Microsoft parking lot with the vanity plate "FEATURE".) These semantics for rename go all the way back to when I wrote DOS v.1. Characters in the new name are substituted one by one for characters in the old name, unless a wildcard character (? or *) is present in the new name. Without adding the blank(s) to the new name, remaining characters are copied from the old name.
xcopy /s/y J:\"My Name"\"FILES IN TRANSIT"\JOHN20101126\"Missing file"\Shapes.atc C:\"Documents and Settings"\"His name"\"Application Data"\Autodesk\"AutoCAD 2010"\"R18.0"\enu\Support\*.*"
..should do it.
Good idea to do an:
IF NOT EXIST "C:\Documents and Settings\His name\Application Data\Autodesk\AutoCAD 2010\R18.0\enu\Support\Shapes.atc" ECHO/ && ECHO/ && ECHO * * * * * COPY FAILED - Call JustME at 555-555-1212 && ECHO/ && pause
(assuming you've done a rename of previous version to .old)
XCOPY /Z <----- restartable mode - good for large files.
The virtual parent trick
Assuming you have your source and destination file in
%SRC_FILENAME% and %DST_FILENAME%
you could use a 2 step method:
#REM on my win 7 system mkdir creates all parent directories also
mkdir "%DST_FILENAME%\.."
xcopy "%SRC_FILENAME% "%DST_FILENAME%\.."
this would be resolved to e.g
mkdir "c:\destination\b\c\file.txt\.."
#REM The special trick here is that mkdir can create the parent
#REM directory of a "virtual" directory (c:\destination\b\c\file.txt\) that
#REM doesn't even need to exist.
#REM So the directory "c:\destination\b\c" is created here.
#REM mkdir "c:\destination\b\c\dummystring\.." would have the same effect
xcopy "c:\source\b\c\file.txt" "c:\destination\b\c\file.txt\.."
#REM xcopy computes the real location of "c:\destination\b\c\file.txt\.."
#REM which is the now existing directory "c:\destination\b\c"
#REM (the parent directory of the "virtual" directory c:\destination\b\c\file.txt\).
I came to the idea when I stumbled over some really wild ../..-constructs in the command lines generated from a build process.
I had exactly the same problem, where is wanted to copy a file into an external hard drive for backup purposes.
If I wanted to copy a complete folder, then COPY was quite happy to create the destination folder and populate it with all the files.
However, I wanted to copy a file once a day and add today's date to the file.
COPY was happy to copy the file and rename it in the new format, but only as long as the destination folder already existed.
my copy command looked like this:
COPY C:\SRCFOLDER\MYFILE.doc D:\DESTFOLDER\MYFILE_YYYYMMDD.doc
Like you, I looked around for alternative switches or other copy type commands, but nothing really worked like I wanted it to.
Then I thought about splitting out the two different requirements by simply adding a make directory ( MD or MKDIR ) command before the copy command.
So now i have
MKDIR D:\DESTFOLDER
COPY C:\SRCFOLDER\MYFILE.doc D:\DESTFOLDER\MYFILE_YYYYMMDD.doc
If the destination folder does NOT exist, then it creates it.
If the destination folder DOES exist, then it generates an error message.. BUT, this does not stop the batch file from continuing on to the copy command.
The error message says:
A subdirectory or file D:\DESTFOLDER already exists
As i said, the error message doesn't stop the batch file working and it is a really simple fix to the problem.
Hope that this helps.

Resources