have a trouble with batch script to copy files only once - batch-file

New to batch scripting..
I want to copy files from one folder(A) to another folder(B) continuously. The other software "moves" files from folder B. My script with Xcopy is continuously copying files from A to B. But When the copied files are moved from B, script is copying again the same files to B. Script should copy files from A to B only once.

You could have shown us the script and made things easier.
From the prompt, execute
xcopy /?
to show xcopy options.
I'd suggest the /d option would do what you need.

Every file has an archive attribute. This attribute was created to determine when a file needs to be copied (well, more or less). By default, files are generated with this attribute set and any change to the file will set it again.
xcopy includes two switches: /a and /m that handle this attribute.
/a tells xcopy to only copy files that have the archive attribute set
/m tells xcopy to only copy files that have the archive attribute set and clear the attribute
You should try something like xcopy /m "c:\sourceA\*" "c:\targetB" This will copy files with the archive attribute set and remove the attribute from the archive.

Related

How to delete files matching a certain pattern in their name?

I'm creating a batch file that deletes all Rar$DIa0.??? folders in the %TEMP% directory.
Is this possible, and how to do it?
The ??? is three randomized numbers. And that's where I have trouble with - deleting all folders that have Rar$DIa0. in the name.
for /d is designed for just this type of use. Something like this should work (remove one of the % if you're testing from the command line):
for /d %%i in ("%TEMP%\Rar$DIa0.???") do rd "%TEMP%\%%i"
The /d makes it work on directory names instead of file names.
If you want to make it easier on yourself, change to the %TEMP% folder first:
pushdir
cd /d %TEMP%
for /d %%i in ("Rar$DIa0.???") do rd "%%i"
The ??? makes it only act on folders that have three letters after a .. If your folders don't have just a three letter extension, change .??? to .*. If you've got a typo, and there is no actual . in the foldername, just remove it and use Rar$DIa0??? or Rar$DIa0*
You may want to test it first by changing rd to echo to make sure you get the folders you want before actually deleting them.
For more information about for (pun intended) type for /? from a command prompt.
The command line to use in a batch file for this task is:
#for /D %%I in ("%TEMP%\Rar$DIa0.*") do #rd /Q /S "%%I"
Command FOR with option /D searches in folder defined by environment variable TEMP for subfolders with folder name starting with Rar$DIa0. not having hidden or system attribute set.
The loop variable I holds for each found subfolder matching this folder pattern the name of found folder with full path without double quotes although the path to temp folder very often contains 1 or more spaces.
For that reason just the command RD with the parameters /Q for quiet execution and /S for deleting also all subfolders in the specified folder must be called with referencing the current value of loop variable I enclosed in double quotes.
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.
for /?
rd /?
By the way: WinRAR deletes the temporary folders usually automatically, except a file is opened from within an archive for viewing/modifying it in another application and WinRAR is closed before the other application is exited with the opened file. In this case WinRAR can't delete the temporary folder with temporarily extracted file because the file is still opened in another application. Of course also command RD can't delete the temporary folder if this folder is still the current directory of another application or a file in this folder is still opened by another application with a read/write access lock.

How to copy files from a folder tree to a single folder and only the latest files?

How to copy files from a folder tree to a single folder and only the latest files using batch commands?
These copies must happen every one hour and avoid overwrite rather than copy only latest files.
Current command:
for /R "D:\Logshipping\NDWAnalyzer\" %%f in (*.*) do copy "%%f" "D:\LogShipping1\NDWAnalyzer\"
The above command copies every time whole files in the folder rather than I need only to copy the latest - the files which are not present in the destination folder.
This is an easy task using xcopy with parameter /M which results in copying only files with archive attribute set and clearing this attribute after copying. The archive attribute is automatically set for a new or modified file.
#echo off
rem Check before copying for deletion of files in destination directory
rem which were copied already before and not updated in the meantime, i.e.
rem no archive attribute set anymore on file, but file is also not existing
rem anymore in destination directory. The archive attribute is set temporarily
rem on those files before running xcopy. This helps also in case of renaming
rem a file in one of the source directories which was copied already before
rem with previous name to destination directory as the rename operation does
rem not set archive attribute.
for /R "D:\Logshipping\NDWAnalyzer" %%F in (*) do (
if not exist "D:\LogShipping1\NDWAnalyzer\%%~nxF" %SystemRoot%\System32\attrib.exe +a "%%~F"
)
rem Copy from all directories in D:\Logshipping\NDWAnalyzer all files with
rem archive attribute set (= modified or added since last run) to directory
rem D:\LogShipping1\NDWAnalyzer with clearing the archive attribute after
rem copy and with copying also all attributes including read-only attribute.
for /R "D:\Logshipping\NDWAnalyzer" %%D in (.) do (
%SystemRoot%\System32\xcopy.exe "%%~fD\*" "D:\LogShipping1\NDWAnalyzer\" /C /H /I /K /M /Q /R /Y >nul
)
It is up to you if you want to use first + second loop or just second loop.
With removing first loop it would be possible to delete files in destination directory still existing in a source directory or rename a file in a source directory which was copied already before to destination directory without being copied once again.
For more details on the used commands open a command prompt window and run
attrib /?
for /?
if /?
xcopy /?
A help is output for each command which should be read to understand the two loops above.

Command Promp to copy ONLY images from FOLDERS and SUBFOLDERS

I'm wondering if it is possible to set up a batch command to perform this action.
Once .bat file is executed, ALL images from folders and sub-folders would be copied to my location on the desktop.
Example:
Original folder is located:
\intranet\file_location\PP Complete Images (in this folder will be loads of other folders and in those folders there will be .jpg images)
Destination file would be based on the desktop.
So I need to extract .jpg images from all folders and sub-folders.
If image already exists in original folder, skip the image or overwrite as script will be executed every morning.
Or should I look for a software to do this for me?
Existing code:
cd c:
cd\
copy "\\intranet\PP Complete Images\Master Image Folder*.jpg" "C:\Users\username\Desktop\Master Image Folder"
copy "\\intranet\PP Complete Images*.jpg"
exit
How do you want it?
It isn't quite clear to me, how the result exactly should be -- should it be flattened or should it be hierarchical as well?
Look at this for example:
source
folder-1
folder-1-1
image1.jpg
folder-1-2
image2.jpg
cheese.jpg
image3.jpg
some_text.txt
folder-2
folder-2-1
image3.jpg
some_music.mp3
cheese.jpg
target
Should the result be basically a copy of the shown hierarchy (without any other file than the jpgs), or should it be a flattened result like this one:
source
... (see above)
target
image1.jpg
image2.jpg
cheese.jpg
image3.jpg
image3.jpg
How can you do it?
Flattened
You can use DOS' for command to walk directories1 and make a custom function2 to handle the files:
#ECHO OFF
for /r %%f in (*.jpg) do call:copyFile %%f
GOTO END
:copyFile
copy /V /-Y %~1 ..\target
GOTO:EOF
:END
Meaning: for every %%f in the listing of *.jpg from the current working dir, execute function copyFile. The /r switch makes the listing recursing (walk through all subdirectories).
In the function, the argument passed to it (now known as %~1) is passed to the copy function: Copy the file to the target directory which is ..\target in this case. /V lets copy verify the result, /-Y lets it ask for permission to overwrite files. See copy /?!
Very big problem: If you have one or more files in different subfolders of your source directory, which have the same name (like the two cheese.jpgs in my example), you will loose data!
So, I wouldn't recommend this approach, as you risk loosing data (digital cameras are not very creative in naming pictures!).
Hierarchical
Just use robocopy:
robocopy /S <sourcedir> <targetdir> *.jpg
/S creates and copys subfolders as well. You can also use /DCOPY:T to make the directories have the same timestamp than the original ones or /L to preview the actions of robocopy.
Small problem: The /E switch handles subfolders as well, even if they are empty. /S handles subfolders as well, but not, if they are empty. But it handles them, if they are not empty, but have no JPG inside -- so, subfolders without JPGs will result in empty folders in the target folder.
Robocopy has loads of parameters, so check out robocopy /?.
Hope this helps! :-)
1Found here: How to traverse folder tree/subtrees in a windows batch file?
2Found here: http://www.dostips.com/DtTutoFunctions.php
Your existing code:
the cd c: is incorrect. To switch the current drive to c: use
c:
The cd \ is redundant. Your remaining code specifies the directories, so the current directory is irrelevant.
Your first copy command has three problems. Master Image Folder*.jpg means all filenames beginning Master Image Folder and ending .jpg. You probably meant Master Image Folder\*.jpg meaning all files ending .jpg in ...\Master Image Folder\
C:\Users\username\Deskto... is probably an error. It is a literal path, so the actual directory would be C:\Users\username\Deskto... You would probably need C:\Users\%username%\Deskto... to substitute-in the current username.
And then the job would stop on a filename-match, so either you'd be pressing A to overwrite all or you'd be pressing y or n for each name-match.
Your final copy command has no specified destination directory.
You can edit-in your actual code by using the edit button under the original text window, cutting-and-pasting your actual code - censoring if necessary, selecting the resultant code block and pressing the {} button above the edit box which indents each line with the effect of formatting and hilighting the code.
The simplest solution is probably to use
xcopy /d /y /s "\\intranet\PP Complete Images\Master Image Folder\*.jpg" "C:\Users\%username%\Desktop\Master Image Folder\"
which will copy updated files (/d) with automatic overwrite (/y) and scanning subdirectories (/s) from-name/mask to-directory.
This would create an identical directory-hierarchy to the original subtree under the destop's Master Image Folder directory.
You could extend this to
for %%a in (
"\\intranet\PP Complete Images\Master Image Folder"
"\\intranet\wherever\somewhere"
) do xcopy /d /y /s "%~a\*.jpg" "C:\Users\%username%\Desktop\Master Image Folder\"
to perform the same action on multiple directory-subtrees; but you need to ensure that the destination directory is not within any subtree selected for inclusion in the list within the parentheses.
I'd advise against "flattening" the output because if you do that, the latest whatever.jpg from each of the subtrees will end up in your destination directory, without notification that there are many possibly different whatever.jpg versions.
I do believe the solution to your problem would be Robocopy.
Robocopy is just plain awesome!
Here is the syntax of robocopy-
robocopy [Source] [Destination] [File] [...] [options]
Source
Specifies the source folder. Where you want to take the files from.
Destination
Destination directory/folder.
File
Here we are! This is what will help you. Here you can specify an extension you want to move. So in your case, your code would look somewhat like this.
robocopy *.jpg c:\destinationdir /S /MAX:1048576
*To execute this .bat every morning go to a program called task scheduler, dont worry, its built into windows. http://windows.microsoft.com/en-US/windows/schedule-task#1TC=windows-7
*Then Click on Create basic task, and set your task to whenever you like!
Thanks guys for your help!!!
I got it solved and there is a code below if someone would ever need something similar:
pushd Z:\intranet\PP Complete Images\
for /r %%a in (*.jpg) do (
XCOPY /Y "%%a" "C:\Users\username\Desktop\Master Image Folder"
)
popd

Adding copy\overwrite logic to a batch file

Good day. I am trying to write my first batch file. I finally got it do to the most basic of tasks, and have read much here that helped including tutorials. I have not yet found an article to help me put what I'm looking for together. My search-fu is weak.
I want my batch file to copy all files every 30 minutes. However, if it comes to a file that has been updated, I want it to copy but not replace the existing in the destination. I'm assuming it would just add the (1) or 'copy' to the file name. I'm not sure if I used the proper switches or need to change them based on what I'm looking for. I think they're good, but I digress.
Here is the batch that I created without the logic:
REM Backup files 30 minutes
#echo off
:start
XCOPY "C:\source directory" "C:\target directory" /d /c /s /r /y /i
TIMEOUT /t 1800 /nobreak
goto start
Normal behaviour is to overwrite the file, or to fail (depending on the action). The (1) or (copy) postfixes are special features of Windows Explorer (the shell). If you want similar behaviour in your script, you'll have to implement it yourself.
The easiest thing (also to prevent a lot of (1), (2) .. (N) files, is to create separate folders. You can create a folder with a timestamp and copy all modified files to it.
To detect which files are modified, you might use the Archive flag of the files. When a file is modified, its Archive flag is set. XCopy has the possibility to copy only those files which have the flag set. Actually the main purpose of this flag is to determine modified files (or at least, files you want to archive).
So my suggestion:
Create a folder with a timestamp in the name. You may want to use the answer to this question for that.
Use XCopy with the /M parameter. /M copies only files with the Archive attribute, and clears the attribute afterwards.
Try to delete the directory using rd or rmdir, but without the /S parameter. It will fail if it contains files, but this way you will prevent a lot of empty directories.
Before implementing this, make sure that the process which modifies the files, also sets the Archive attribute again. It should do that automatically, but it can't hurt to test this.
-edit- Per request an example:
REM Backup files 30 minutes
#echo off
:start
REM generate a timestamp value that can be used as a file name.
setlocal TIMESTAMP=%DATE:~10,4%-%DATE:~4,2%-%DATE:~7,2%-%TIME:~0,2%-%TIME:~3,2%-%TIME:~6,2%
REM Not needed, I think: Creating the directory yourself.
REM md "C:\target directory\%TIMESTAMP%"
REM /S for recursive. /I should create target directory? /M for backup mode.
XCOPY "C:\source directory" "C:\target directory\%TIMESTAMP%" /M /S /I
REM Not needed, I think: Removing the directory (if it's empty).
REM rd "C:\target directory\%TIMESTAMP%"
TIMEOUT /t 1800 /nobreak
goto start
I think /I already solves the other issues. It assumes that target is a directory if it doesn't exist. That makes me assume that it will in fact create that directory if it doesn't exist, and probably only if there is anything to copy. If that is right, you also won't have to remove the directory if it's empty.
Considering cleanup: Remember that this method (using /M) only copies files that have changed. If you cleanup old directories, you should make sure to copy the entire folder first. The timestamped folders will contain only the modified files (incremental backup), so if you clean up old ones, your backup/copy won't be complete anymore!

xcopy does not create directory structure

I have a strange problem with xcopy in Windows XP Professional. I don't know if its a stupid question as I am specifying only a file as the source, so should I even expect any other behavior ? This is it:
I am using xcopy <src> <dest> /s/y.
<src>=C:\sourcefolder\a\b\c\d\something.java and
<dest>=C:\destinationfolder.
Now xcopy copies the file but does not create the directory structure \a\b\c\d\ inside C:\destinationfolder .
what I want is C:\destinationfolder\a\b\c\d\something.java and
what I get is C:\destinationfolder\something.java
I have tried to run it in destination folder C:\destinationfolder by specifying a . for target folder
Tried it without any target in above
There is a script I have which calls xcopy iteratively so I am left with C:\destinationfolder\many java files without any directory structure.
A. Yes I have done xcopy /? to see all options
B. /T also does not create any empty directory structure
C. I can not go to source folder a\b\c\d\ and run xcopy . <dest>
UPDATE
I removed my previous answer on using ROBOCOPY. I believe the following will do what you want using XCOPY.
Assuming your folder structure is like this:
SOURCE = C:\MyJavaStuff\A\B\C\D\something.java
DEST = C:\MyDestination
Run XCOPY like this:
XCOPY C:\MyJavaStuff\something*.java C:\MyDestination /S /E
Note the * in something*.java.
The problem is that you are specifying which file to copy in the source. xcopy won't create the folder structure in this case. However, if you change your call to xcopy to
xcopy *.java C:\myfolder /s/y
it will copy the .java files and the folder structure as well. You need to specify a wildcard for this call to work as you want. If you want only to copy specific files, you will have to adjust the call to xopy, e.g.:
xcopy something.jav* C:\myfolder /s/y
Edit
You say that you get the list of files to copy from another command. If you can output this list of files in a text file, you could do the following:
FOR /F "tokens=* delims=," %F in (d:\test\list.txt) DO xcopy src\%~nxF* .\dest /S /Y
What this command does is read a text file ("d:\test\list.txt" in this case), read every line, and for each file, run xcopy, adding a wildcard at the end of the file name to make sure it creates the folder structure.
I'm assuming here that:
You can get the list of files in a text file, with only the file names (and optinally the paths)
You know the source folder ("C:\sourcefolder" in your example, the folder structure "a\b\c\d" does not need to be known) and can use it in the FOR command.
You can also use the following form:
FOR /F "tokens=* delims=," %F in ('cmd') DO xcopy src\%~nxF* .\dest /S /Y
where cmd needs to be replace with the command you use to generate your list of files to copy.
Note that if you use this FOR command in a batch file, you need to replace %F with %%F (and %~nxF* with %%~nxF*).
I had a look at the xcopy switches and you can copy the directory structure with /T, although that doesn't copy empty directories you can override this with /E. So your command would look like this:
xcopy C:\sourcefolder\a\b\c\d\something.java C:\destinationfolder /T /E /S /Y
Hope this helps!
In order to get C:\destinationfolder\a\b\c\d\something.java XCOPY needs to know how much of C:\sourcefolder\a\b\c\d\something.java to duplicate.
You can use:
C:
cd \sourcefolder
XCOPY something.java* C:\destinationfolder\ /S
Just be aware that this may have the side effect of also copying C:\sourcefolder\oops\something.java to C:\destinationfolder\oops\something.java as well as any other matches for something*.java under C:\sourcefolder\.
It seems to me that xcopy is typically used for copying directory trees, not single files (though it can work). And, xcopy will recreate the directory structure under the source folder in the target folder. If xcopy is given the /i switch, the target folder is assumed to be a directory. It will be created if it does not exist, even if there are multiple parents that need to be created.
You have C:\MyJavaStuff\A\B\C\D\something.java - that is your source. You want to end up with something.java not in C:\destinationfolder, but in C:\destinationfolder\A\B\C\D - so that is your target. You don't even have C:\destinationfolder. That is OK, with /i the entire path will be created.
xcopy /i c:\MyJavaStuff\A\B\C\D\something.java C:\destinationfolder\A\B\C\D
If something.java were the only file under C:\MyJavaStuff, you could also use
xcopy /sei c:\MyJavaStuff C:\destinationfolder
That would recreate the entire tree structure, copying your file. But if there are other files (and folders) under MyJavaStuff they would also be copied.
I have written a very similar batch file using xcopy. Perhaps what I did will help you.
This is the command I used:
xcopy "c:\Data Files\Dave's Data\*.*" "m:\Dave's Data" /R/D /E/H
In this case, Dave's Data on the source contains an entire directory tree containing at least 50,000 files & exceeding 75GB data. It runs perfectly on Windows XP
I found /T was unnecessary as the directory tree is copied. I also found /S was unnecessary as /E copied directories & sub-directories including empty ones. I included /R to copy & overwrite read only files on the destination. /H copied hidden directories. /D copied only newer files. I use this as a daily backup tool for my data.
The only problem I have is while this command will work on Windows 7 the first time, it will not work on subsequent runs when the destination directory tree exists. I suspect this is due to a privilege issue as the xcopy command will work on subsequent runs on Windows 7 within a cmd.exe window.

Resources