0

I hope the title is somewhat comprehensible...

I'd like to scan a large folder (including sub-folders) for a specific list of files and copy those to a new location. So far, I have found the following lines of code:

@echo off &setlocal 
set "sourceRoot=E:\source folder\" 
set "sourceList=list of file names.txt" 
set "destFolder=C:\destination folder\

for /f "delims=" %%i in ('dir /a:-d /b /s "%sourceRoot%\*.jpg"^|findstr /ig:"%sourceList%"') do ( 
  copy "%%~i" "%destFolder%\"
) 
PAUSE

This works just fine but naturally keeps copying all files that include one of the lines from the "sourceList". (for example, if I want to copy "saber.jpg", it will also copy "light saber.jpg" and "sabertooth.jpg") I found and tried commands like "^" and "$" or "/b" and "/e" to tell the code that the results should start AND end with the search string - but to no avail.. Sadly, I have no coding-knowledge whatsoever, and extensive googling didn't get me any further than this.

Is there any way to ensure that only files whose names are IDENTICAL to an entire line from the .txt-file are copied?


Second problem:

Within different sub-folders, there are files that bear the same name (they are different versions of the respective file). Whenever I run the code, they seem to be overwriting one another - leaving me with one version for each file name. Ideally, I would want to copy all the different versions and give the copies an extension, so that they can coexist in the destination folder. (e.g. "saber", "saber1", "saber2", etc.)

I'd like to thank everybody in advance for their help and ideas! :)

kind regards

Malte

(In case it is important in any way: I'm using Windows 7)

aschipfl
  • 33,626
  • 12
  • 54
  • 99
  • 1
    Does `list of file names.txt` contain pure file names, or does it include paths? Anyway, you must provide the `/L` option to [`findstr`](http://ss64.com/nt/findstr.html) for it to not do regular expression searches; you also need the `/E` option; since you are feeding full paths into `findstr`, the `/B` (or `/X`) option cannot be used, but you can precede every file name in `list of file names.txt` with `\\ `(which is an escaped literal `\ `to `findstr`), then you probably get the result you want... – aschipfl Jun 20 '17 at 16:24
  • Be aware that `findstr` if flawed when it comes to multiple search literal strings: [Why doesn't this FINDSTR example with multiple literal search strings find a match?](https://stackoverflow.com/q/8921253) – aschipfl Jun 20 '17 at 16:43
  • Actually I do not like the fact that you posted one question containing actually two totally independent ones; however, since there is already an answer referring to the second one, I suggest to not change anything; but for the future, please write one post per question... – aschipfl Jun 20 '17 at 17:01

2 Answers2

1

This refers to the first problem only, but not to the second one you mentioned in your question!


Given that the file list of file names.txt cantains pure file names only but no file paths, your findstr search can be anchored to the end of each line by the /E option, but it cannot be anchored to the beginning, because you feed absolute paths into findstr rather than pure file names, since dir /B returns full paths when the /S option is provided.

What you can do is to precede every file name in list of file names.txt by \\, which is an escaped literal backslash for findstr, which in turn is the Windows path separator.

...
set "sourceList=list of file names.txt"
set "tempList=%TEMP%\augmented list.tmp"
...
> "%tempList%" (
    for /F "usebackq delims= eol=|" %%L in ("%sourceList%") do (
        echo(\\%%L
    )
)
...

Then adapt your piped findstr command line like this (with /L added to force literal search):

    dir /A:-D /B /S "%sourceRoot%\*.jpg" ^| findstr /L /I /E /G:"augmented list.tmp"

Finally, after having done the copying, clean up the temporary list file:

...
del "%tempList%"
aschipfl
  • 33,626
  • 12
  • 54
  • 99
0

first problem:

/x

instead of /b , etc. means exact match

(see findstr /? from the prompt)

second problem:

instead of copy "%%~i" "%destFolder%\"

if exist "%destFolder%\%%i" (
 set "copied="
 for /L %%c in (2,1,7000) do if not defined copied if not exist ""%destFolder%\%%~ni%%%c%~xi" copy "%%~i" "%destFolder%\%%~ni%%%c%~xi"&set "copied=Y"
) else ( 
 copy "%%~i" "%destFolder%\"
)

First, see whether the raw destination filename exists. If not, copy the file.

If it does, clear the flag value copied, and loop for %%c = 2 to 7000 step 1: (if the copied flag is NOT set and the filename basename%%c.extension does NOT exist, then copy to basename%%c.extension and set to flag copied to a value)

the for documentation

for /?

from the prompt will show what the metavariable-modifiers are (%%~ni = the name part of %%i, %%~xi = the extension part, etc.) %%c is simply a string with an incrementing numeric value.

Note that if defined operates on the run-time value of the variable, so that it can act as a flag.

Magoo
  • 77,302
  • 8
  • 62
  • 84