简体   繁体   中英

Copy a directory tree to a single directory at a command line

Anyone know of a command line utility (or one that can run as a command line) that will collect all the .jpg files in a directory tree to a single folder, only copying files that change?

I started with Renamer , which is great for renaming files in their current directories, but fell short when I tried to mangle the path. This is probably because I don't know Renamer that well. I ended up creating a text file directory dump, then using a REGEX find / replace to create a batch file, but this is hardly efficient nor automated.

The REGEX:

(G:\\DIR\\DIR\\)([0-9]+\\)([0-9]+\\)([0-9]+\\)([0-9]+\\)(p[0-9]+.jpg)

changed this

G:\\DIR\\DIR\\00\\00\\00\\00\\p0000000000.jpg

to this

G:\\DIR\\DIR\\p0000000000.jpg

(copy \\1\\2\\3\\4\\5\\6 \\1\\6) in the batch file.

I need to run the whole thing as a scheduled task without a real person logging in. Not really looking for a Zip file because I don't want to disturb the system processor, plus most of the files will not change from day to day. This is more of a file sync.

In a Windows command line you can do this:

for /R A %i IN (*.jpg) DO xcopy %i B /M /Y

Where A is the source directory and B is the destination directory. You need to have command extensions enabled, which I believe is the default.

A couple of notes from the comments:

If any of your paths could have spaces in you will need to add quotes around the second %i. This prevents the string being interpreted by the xcopy command as two separate parameters. You may need to do the same around A and B paths. Like this:

for /R "A" %%i IN (*.jpg) DO xcopy "%%i" "B" /M /Y

If you are putting this inside a .bat or .cmd file you will need to double the percentage like this.

for /R A %%i IN (*.jpg) DO xcopy %%i B /M /Y

The /M option on xcopy will only copy files with the Archive bit set and then unset this bit. This prevents the files being copied twice. If you have other processes that also alter this bit it may cause issues. It is also possible to use the /D option which compares the file's last modified time with that in the destination and only copies newer files.

I'm guessing you're on Windows from the path format.

I've not read the whole thing, but http://www.infionline.net/~wtnewton/batch/batguide.html#6a might help you.

The same page has dizzy.bat, ( http://www.infionline.net/~wtnewton/batch/dizzy.bat ) which should be trivial to edit to do what you want.

In a Unix environment I would use find or rsync (and maybe some features of the shell). Cygwin and MinGW come with find , maybe with rsync . You can also probably get a standalone port of find for Windows somewhere.

If the SOURCE shell variable is the directory containing subdirectories with files to copy, and the DEST shell variable is the directory to copy them to:

find $SOURCE -name \*.jpg -exec cp --update \{\} $DEST/ \;

find is by nature recursive. " -name \\*.jpg " selects files that match that pattern. You can add additional conditions with -and. The --update option to the cp command (or -u) only bothers copying the file if changed or not yet copied. There are other options to cp that might be useful too.

If $SOURCE is the same as $DEST as in your DIR/DIR/ example, then find will also find the destination files (already copied), though this will be ok, cp will recognize that you are trying to copy the same file to itself and skip it, but if you want to avoid that wasted work you can use 'for' and 'if' (or something) to only run find on the subdirectories of DIR/DIR/.

You can also use rsync, which has options that can delete files from the destination directory if they have also been deleted from the source directory, and many other such variations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM