M.shadow
M.shadow

Reputation: 135

forfiles command ignore a directory

I want to write a batch that finds all docs less than 50 mb in c:\ and copy them in a folder but ignore system directory docs. I prefer it does not even search in the system dir.

Here is my batch that finds and copies all files less 50 mb in right directory but i can not make it to ignore system from searching or C:\Windows directory.

@ECHO off
:: variables

SET odrive=%odrive:~0,2%
SET backupcmd=xcopy /s /c /d /e /h /i /r /y

MKDIR "C:\Users\Documents\USBBackups\DOC\C"

forfiles /P C:\ /M *.DOC* /S /C "cmd /c if @fsize leq 50000000 echo @PATH "  > "C:\Users\Documents\USBBackups\DOCC.txt"
FOR /F "tokens=*" %%a in (C:\Users\Documents\USBBackups\DOCC.txt) do xcopy %%a "C:\Users\Documents\USBBackups\DOC\C" /c /h /i /r /y

@ECHO off

Upvotes: 3

Views: 12571

Answers (2)

aschipfl
aschipfl

Reputation: 34909

There is no way to tell forfiles to exclude certain directories when switch /S is provided. You will have to write your own code that does that.

I would not use forfiles for that due to poor performance, but standard for instead:

@echo off
for /D %%D in ("%SystemDrive%\*.*") do (
    if /I not "%%D"=="%SystemRoot%" (
        pushd "%%D"
        for /R %%F in ("*.doc?") do (
            if %%~zF LEQ 50000000 (
                echo %%F
            )
        )
        popd
    )
)

Here the root directory level is enumerated by for /D. All directories other than %SystemRoot% are enumerated recursively by for /R.

I changed the search pattern from *.doc* to *.doc? in order not to include files ending in .doc.lnk for example, which I guess you do not want to be retrieved.

Instead of the echo command you can directly place your xcopy command line with "%%F" provided as the copy source.


You can do the same directly in command prompt as a one-liner, like this:

for /D %D in ("%SystemDrive%\*.*") do @if /I not "%D"=="%SystemRoot%" pushd "%D" & (for /R %F in ("*.doc?") do @if %~zF LEQ 50000000 echo %F) & popd

I recommend not to walk through the entire directory tree and later filtering by something like findstr /V /I /L /B /C:"%SystemRoot%", because in that case you were wasting time enumerating a huge number of items which you ignore afterwards.

However, if you do want to rely on forfiles /S, the working command line looks like this:

2> nul forfiles /S /P "C:\\" /M "*.doc*" /C "cmd /C if @isdir==FALSE if @fsize LEQ 50000000 echo @path" | findstr /V /I /L /B /C:"\"%SystemRoot%"

Upvotes: 4

user5721973
user5721973

Reputation:

Adapt this technique of using findstr to filter out certain names.

To see size of folders in Documents, excluding music, video, or pictures folders.

for /f "skip=3 tokens=3" %A in ('Reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "Personal"') do set doc=%A

for /f "usebackq tokens=2* delims= " %i IN (`dir "%doc%" /a /s ^|findstr /i /v "\/"^|findstr /l /v "Pictures Music Video"`) DO @echo %j&echo.

However you could start the forfiles command in the c:\users or the particular users home folder (%userprofile%). You specify to start at c:\ which includes all folders.

forfiles /P %userprofile% /M .DOC /S /C "cmd /c if @fsize leq 50000000 echo @PATH "
forfiles /P c:\users /M .DOC /S /C "cmd /c if @fsize leq 50000000 echo @PATH "

Upvotes: 0

Related Questions