forfiles command ignore a directory - batch-file

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

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%"

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 "

Related

How to define a folder to search in and search for files smaller than X KB within a date range?

I have found the following example which enables me to search for files within a certain date range which I can modify to use the variables.
#echo off
setlocal
FOR /F "delims=*" %%A IN ('forfiles /d -24-08-2021') DO (FOR /F "delims=*" %%B IN ('forfiles /m %%A /d +01-03-2021') DO (ECHO %%B)) 2>Nul
I have tried to replace (ECHO %%B) with another example that looks for files smaller than X Forfiles /S /M * /C "cmd /c if #fsize LSS 120000 echo #file into the final result:
FOR /F "delims=*" %%A IN ('forfiles /d -24-08-2021') DO (FOR /F "delims=*" %%B IN ('forfiles /m %%A /d +01-03-2021') DO (Forfiles /S /M * /C "cmd /c if #fsize LSS 120000 echo #file)) 2>Nul
but the combination does not work and I cannot figure out why.
It's not that clear to me what you're trying to do: it seems like you want file, which are more recent than an old date and smaller than a given size, this can be achieved like this:
Prompt>forfiles /d +01/01/2021 /C "cmd /c if #fsize lss 120000 echo #file"
/d : filters out the files, based on its date
if #fsize : filters out the files, based on its size

Unable to Delete empty folders of directory and sub-directory using batch

with the help of batch file I am able to delete files from the main directory and sub directories but I am finding it difficult to delete empty sub directories left after files inside it got deleted . I have written script but it is not working for deleting empty sub directories part
MY Batch Script
#echo off
Set _Extentions=".LOG"
Set _FolderList= "D:\FCS"
Set _FolderList=%_FolderList% "D:\SMSGateway\SMSLogs"
Set _NoOfDays=15
for %%s in (%_FolderList%) do (
for %%d in (%_Extentions%) do (
call :process_Deletion %%s %%d
)
)
:process_Deletion
IF [%1] == [] GOTO EndOfFun
set _ParaPath=%1
set _ParaExtn=%2
echo forfiles /P %_ParaPath% /S /m *%_ParaExtn% /D -%_NoOfDays% /C "cmd /c if #isdir==FALSE echo #path #fdate #ftime"
echo forfiles /P %_ParaPath% /S /m *%_ParaExtn% /D -%_NoOfDays% /C "cmd /c if #isdir==FALSE del #file"
echo for /f "delims=" %%d in ('dir %_FolderList% /s /b /ad ^| sort /r') do rd "%%d"
:EndOfFun
EXIT /B
What am I doing wrong here ? Please help..
Empty directories require rd or rmdir
https://www.computerhope.com/rmdirhlp.htm
The rd and rmdir commands remove empty directories in MS-DOS. To delete directories with files or directories within them, you must use the deltree command. If you are running Microsoft Windows 2000 or Windows XP, use the /S option.

Issue Getting a Mass Name change .bat on a share to add spaces to the new file name

I know someone out there has a nice quick solution for this: I just believe I am missing something. I am slightly new to creating bat files. I have roughly 2,000 files with improper naming on a share drive.
The below bat gets me started but I need to have the new file name include spaces but when I try it gives an invalid syntax command even with the ' " '.
Line 3, 3.MRF, is where it is giving me the syntax error '-' is not a valid command.
#echo
forfiles /S /M "1.PURCHASE*.*" /C "cmd /c rename "1.PURCHASE*.*" "2.PURCHASE*.*""
forfiles /S /M "3.MRF*.*" /C "cmd /c rename "3.MRF*.*" "1.MRF - *.*""
forfiles /S /M "3.ACOMRF-*.*" /C "cmd /c rename "3.ACOMRF-*.*" "1.ACO-MRF-*.*""
forfiles /S /M "2.RECEIPT*.*" /C "cmd /c rename "2.RECEIPT*.*" "3.RECEIPT*.*""
forfiles /S /M "2.RECIEPT*.*" /C "cmd /c rename "2.RECIEPT*.*" "3.RECEIPT*.*""
:exit
#pause
Perhaps run a for loop instead, it just looks much better to start off with:
#echo off
for /r /d %%a in (*) do (
pushd "%%~a"
ren "1.PURCHASE*.*" "2.PURCHASE*.*"
ren "3.MRF*.*" "1.MRF - *.*"
ren "3.ACOMRF-*.*" "1.ACO-MRF-*.*"
ren "2.RECEIPT*.*" "3.RECEIPT*.*"
ren "2.RECIEPT*.*" "3.RECEIPT*.*"
popd
)
Here you need one loop that will pushd to each of the subdirectories, rename anything that matches the rename parameter.
I would suggest using String Manipulation within a simple for-loop.
#echo off
setlocal enabledelayedexpansion
FOR %%A IN (3.MRF*.*) DO (
SET name=%%A
rename "!name!" "!name:3.MRF=1.MRF - !"
)
Before:
3.MRF A.txt
3.MRF B.txt
3.MRF C.txt
After:
1.MRF - A.txt
1.MRF - B.txt
1.MRF - C.txt
Update
Made a more generic solution which lets you define all search and replace strings. Moreover it works on all subdirs now.
#echo off
setlocal EnableDelayedExpansion
PUSHD "%0\.."
REM <search_1>;<replace_1|<search_2>;<replace_2>|...|<search_n>;<replace_n>
SET SearchAndReplace=3.MRF - ~1.MRF - ;3.ACOMRF-~1.ACO-MRF-
REM Replace ; with \n
SET SearchAndReplace=!SearchAndReplace:;=^
!
REM iterate over search and replace tokens
FOR /F "tokens=1,2 delims=~" %%G IN ("!SearchAndReplace!") DO (
set search=%%G
set replace=%%H
FOR /F "usebackq delims=" %%I IN (`dir /S /B /A:-d "*!search!*" 2^>nul`) do (
set file="%%I"
REM hack to allow replace !replace! for !search! in !file!
FOR /F "delims=" %%J IN ("!search!") do (
FOR /F "delims=" %%K IN ("!replace!") do (
echo move !file! !file:%%J=%%K!
move !file! !file:%%J=%%K!
)
)
)
)
POPD
Set the SearchAndReplace variable as needed (see comment).

How to I delete from all Sub Directories apart from a select few

I would like to create 1 batch file that deletes a type of file (i.e. ".bak") with different date ranges situated in different sub folders that are in the same patent folder, but I can list the minority of folders.
I have managed to create a FOR loop to look in certain directories (which the directories are set in a variable), deleting any '*.bak' file over a certain age with the below script:
SET "WeeklyBAKLocation=Folder20 Folder21 Folder25 Folder28"
SET WeeklyBAK=7
SET DailyBAK=3
FOR %%x IN (%WeeklyBAKLocation%) DO forfiles /p "%%x" /s /m *.bak /d -%WeeklyBAK% /c "cmd /c DEL #path /q"
<SECOND FOR LOOP below HERE>
The above works deleting .bak files older than 7 days in those folders, my question is how can I reverse that and delete '.bak' files in every other directory that's older than 3 days, without deleting the ones kept from the first query?
I tried nesting FOR and FORFILES, using findstr /v to ignore them as below (but it would ignore each directory for that 1 loop, and then delete it for the next loop wouldn't it, so eventually it would not have worked and is massively inefficient?)
SET "WeeklyBAKLocation=Folder20 Folder21 Folder25 Folder28"
SET WeeklyBAK=7
SET DailyBAK=3
<First FOR LOOP above HERE>
FOR %%x IN (%WeeklyBAKLocation%) DO FOR /F "delims=*" %%G IN ('dir /b /s "%~dp0" ^| findstr /v "\%%x"') DO forfiles /p "%%G" /s /m *.bak /d -%DailyBAK% /c "cmd /c ECHO #path /q"
Essentially can I ignore SOME directories at once when walking through them to find .bak files to delete only ones that are 3 days old.
Many thanks in advance.
FOR /F "delims=*" %%G IN (
'dir /b /s /AD "%~dp0" ^| findstr /v "\%%x"') DO (
set "zapme=Y"
FOR %%x IN (%WeeklyBAKLocation%) DO if /i "%%x"=="%%G" set "zapme="
if defined zapme forfiles /p "%%G" /s /m *.bak /d -%DailyBAK% /c "cmd /c ECHO #path /q"
)
read the directory list in basic form (note /ad) and for each directory, set zapme to something then check whether the directory is not to be processed and set zapme to nothing if it's one of those directories. The zapme flag can then be tested for being set or not set. If it's set, go ahead and process the directory.
FOR /F "delims=*" %%G IN (
'dir /b /AD "%sourcedir%"') DO (
set "zapme=Y"
FOR %%x IN (%WeeklyBAKLocation%) DO if /i "%%x"=="%%G" set "zapme="
if defined zapme ECHO forfiles /p "%sourcedir%\%%G" /s /m *.bak /d -%DailyBAK% /c "cmd /c ECHO #path /q"
)
...happens every time I don't actually test it...

Forfile command to delete all except a directory

I want to use the forfile command to delete all .frm files in some directories. But, I don't want to delete the *.frm files under a specific directory.
I have this, but i don't know how to put the name of the dir where i don't want to delete files:
forfiles /p D:\myfolder\ /s /m *.frm /c "cmd /c IF NOT DESIRE_DIR del #PATH"
Some help, please !
#for /f "delims=" %A in ('dir /ad /b^|findstr /l /v /i "Dirname1 Dirname2"') do #echo %A
This is also a lot quicker than forfiles. Forfiles is only really useful when listing files by date.
Put your folder names in Dirname1, Dirname2 to exclude them. Spaces mean or.
Remember in a batch file %A becomes %%A.
forfiles /p D:\myfolder\ /s /d -7 /m *.frm /c "cmd /c echo #path >> %temp%\temp.txt"
for /f "delims=" %A in ('findstr /i /v "list of excluded directories" ^< "%temp%\temp.txt"') do echo %A
Your /m was also in the wrong place and you would have seen a message telling you that.

Resources