Batch - Delete a specific file with forfiles - windows

I want to do echo only checking the date from one file with forfiles:
forfiles /m "C:\Backups\TEST.bak" /c "cmd /c echo test" /d -1
But it returns me an error:
The System cannot find the file specified.
And that file it exists and the directory is correct.
If use forfiles in the same directory (without file) it works fine:
forfiles /p "C:\Backups" /c "cmd /c echo test" /d -1
What am I doing wrong?

forfiles /p "c:\Backups" /m "test.bak" /d -1 /c "cmd /c echo #fdate #ftime"
/p needs a folder to start searching
/m needs a file mask to indicate what to search

The problem is that forfiles requires a directory as parameter. You are giving it a file instead. This won't work.
Instead you should do this:
FOR %%a in (C:\Backups\TEST.bak) DO SET FileDate=%~ta
This will store the file's modifed date in %FileDate%.

Related

Batch - Looping through text file [duplicate]

This question already has answers here:
How to read file contents into a variable in a batch file?
(4 answers)
Closed 2 years ago.
I'm trying to find all files older than 30 days in several directories using this command:
[Directory] && forfiles /d -30 /c "cmd /c echo #path"
The output is a .txt file.
The text file contains the path to the directory:
C:\Directory1
C:\Directory2
C:\Directory3 etc
I'm trying to loop through several directories using a text file but I need to provide 2 commands:
cd (to change to the directory whose files I need info on) and the actual command to get the information)
If I create a batch file entering the directory names manually I have something like this:
cd "C:Directory1" && forfiles /d -30 /c "cmd /c echo #path"
cd "C:Directory2" && forfiles /d -30 /c "cmd /c echo #path"
cd "C:Directory3" && forfiles /d -30 /c "cmd /c echo #path"
How do I enter the "cd" command at the beggining of the loop, then the directory which is in the txt file and the rest of the command (forfiles /d -30 /c "cmd /c echo #path")
What I have so far is:
for /f "usebackq tokens=*" %%A in ("C:\list.txt") do forfiles /d -30 /c "cmd /c echo #path %%A
Thanks!
The FOR command with the /F option is used to read a file and it assigns each iteration of the file to the variable %%A. So use the that variable with the /P option of the FORFILES command.
for /f "usebackq tokens=*" %%A in ("C:\list.txt") do forfiles /P "%%~A" /d -30 /c "cmd /c echo #path"

forfiles in certain subfolder in multiple folders

Is there away to only display files in a folder called "Export", when such a subfolder is in multiple locations?
This will display all .xlsx files below where I'm running the batch file from, however I don't want to display all, I only want to display things in a folder called "Export":
forfiles -p "%~dp0\" -s -m *.xlsx -d -365 -c "cmd /c ECHO #relpath"
I have attempted things like:
forfiles -p "%~dp0\*\Export" -s -m *.xlsx -d -365 -c "cmd /c ECHO #relpath"
However it doesn't recognise syntax like this. Says invalid argument/option, but they are valid until I add *\ to the path.
This is an example of the structure I'm working with and what I what results to display:
%~dp0\1\Exports\Excel\ - (Do display .xlsx files)
%~dp0\1\Do Not Delete\Excel\ - (Don't display .xlsx files)
%~dp0\2\Exports\Excel\ - (Do display .xlsx files)
%~dp0\2\Do Not Delete\Excel\ - (Don't display .xlsx files)
The number folders would be a variable somehow, which is why the *\ is in my attempt.
I will then edit this to delete the files when I know it's picking up the right ones.
You could use two nested forfiles loops:
forfiles /S /P "%~dp0\" /M "Export*" /C "cmd /C if #isdir==TRUE forfiles /P #path\Excel /M *.xlsx /D -365 /C 0x22cmd /C echo 00x7840path0x22"
This command line walks through the given root directory (%~dp0) recursively and iterates through all items matching Export* (you might replace this pattern by Export or Exports, depending on your needs); the hierarchy depth is not checked in order to avoid the need of three nested loops. Anyway, if the iterated item is a directory, the sub-directory Excel is enumerated and searched for items matching *.xlsx.
Supplement:
The above command line may display many error messages like ERROR: The specified directory does not exist. or ERROR: Files of type "*.xlsx" not found., depending on your data; to avoid them, redirect STDERR to the nul device:
2> nul forfiles /S /P "%~dp0\" /M "Export*" /C "cmd /C if #isdir==TRUE forfiles /P #path\Excel /M *.xlsx /D -365 /C 0x22cmd /C echo 00x7840path0x22"
The forfiles command returns an empty line to STDOUT, so the above command line will contain many of them; to avoid such too, redirect STDERR and STDOUT to the nul device and redirect only the wished data to the console con:
1> nul 2>&1 forfiles /S /P "%~dp0\" /M "Export*" /C "cmd /C if #isdir==TRUE forfiles /P #path\Excel /M *.xlsx /D -365 /C 0x22cmd /C 1> con echo 00x7840path0x22"
You can send results with | to FINDSTR like this:
FORFILES /P . /S /M *.xlsx /D -365 /C "CMD /C ECHO #path" | ^
FINDSTR "\\Exports\\" | ^
FINDSTR /I /C:Delete /V
So you search every xlsx files located in a certain path (here is current dir) Every xlsx must contain Exports as folder and show every xlsx that doesn't (/V Displays only the non-matching lines) contain "delete" (/I mean insensitive)
In a batch file you can replace /P . by any variable path /P "%~dp0" /P "%CD%" or send as argument /P %1
Also you can do FOR loop to make any command for every match.
In one line to put in console:
FOR /F "usebackq delims=" %A in (`forfiles /p . /s /m *.xlsx /D -365 /C "cmd /c ECHO #path" ^|FINDSTR "\\Exports\\" ^|FINDSTR /I /C:Delete /V`) DO #ECHO FAKE-COMMAND %A
In a batch file:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "usebackq delims=" %%A in (
`forfiles /p . /s /m *.xlsx /D -365 /C "cmd /c ECHO #path" ^|FINDSTR "\\Exports\\" ^|FINDSTR /I /C:Delete /V`
) DO (
SET "myfile=%%~A"
#ECHO FAKE-COMMAND "!myfile!"
)
ENDLOCAL
GOTO :EOF

How to use forfiles to delete files without extension

I am using forfiles to delete files older than 7 days from a specific directory using the following script found elsewhere on this forum:
forfiles -p "H:\E-drev" -m *.* /D -7 /C "cmd /c del #path"
This Works fine except I have some files with no extension eg. a file named TA07l. This file is not deleted. I have tried using #fname instead of #path but this does not help.
Any advice would be greatly appreciated.
The following should work:
forfiles /P "H:\E-drev" /M * /D -7 /C "cmd /C if #isdir==FALSE if #ext==\"\" del #path"
You have to use * instead of *.* because otherwise it will search every files that contain a dot .
Update with few examples between * and *. and *.*:
copy nul _onefilewithoutext
copy nul _onefilewith.ext
mkdir _oneFolder
dir /b /a-d *.
_onefilewithoutext
Forfiles command
forfiles /M *. /C "cmd /C echo #relpath"
Error: File Type "*." not found.
forfiles /M * /C "cmd /C echo #relpath"
".\_onefilewith.ext"
".\_onefilewithoutext"
".\_oneFolder"
forfiles /M *.* /C "cmd /C echo #relpath"
".\_onefilewith.ext"
forfiles /M * /C "cmd /C if #isdir==FALSE echo #relpath"
".\_onefilewith.ext"
".\_onefilewithoutext"
forfiles /M * /C "cmd /C if #isdir==FALSE if #ext==\"\" echo #relpath"
".\_onefilewithoutext"

Delete file longer then 30 days old for long path and long file name

I tried to make batch file in windows by using task schedule once a month to find *.bak. With condition more then 30 old. I create two condition full path name and non-8dot3 path name. For those unable to delete it be recorded to a TXT file.
Here the command I found:
forfiles /P E:\WP /S /M *.bak /D -30 /C "cmd /C del #path"
Here is my command for delete using non-8dot3 file names:
forfiles /P E:\WP /S /M *.bak /D -30 /C "cmd /C for %A in (#path) do #echo del %~sA
For file can't be delete because it to long path and file name, it recorded to a TXT file with long full path file name and non-8dot3:
forfiles /P E:\WP /S /M *.bak /D -30 /C "cmd /c echo #path >> list.txt"
forfiles /P E:\WP /S /M *.bak /D -30 /C "cmd /c for %A in (#path) do #echo %~sA" >> list.txt
These 4 command are working well if I just copy and paste into dos command prompt.
But when I put them into batch file e.g. "del30days.bat", it does not working for non-8dot3 file names:
#echo off
:: Set host computer name
set host=%COMPUTERNAME%
:: Set save list path
set list_path=F:\LogFiles
:: Set min age of files and folders to delete
set file_list=ListCantDeleted-%host%-%date:~10,4%-%date:~7,2%-%date:~4,2%.txt
:: Set target folder path
set target_path=E:\WP
:: Set min age of files and folders to delete
set max_days=30
:: Set what kind files or extension
set file_ext=*.bak
:: Delete files from target path
forfiles /P %target_path% /S /M %file_ext% /D -%max_days% /C "cmd /C del #path"
forfiles /P %target_path% /S /M %file_ext% /D -%max_days% /C "cmd /C for %A in (#path) do #echo del %~sA"
:: Record files from target path
forfiles /P %target_path% /S /M %file_ext% /D -%max_days% /C "cmd /c echo #path >> %list_path%\%file_list%"
forfiles /P %target_path% /S /M %file_ext% /D -%max_days% /C "cmd /C for %A in (#path) do #echo %~sA >> %list_path%\%file_list%"
I got this error on non-8dot3 files name but not on long file name on record to a TXT file, by mean it can't delete file using non-8dot3 file names as well.
~sA" was unexpected at this time.
Any reason why?
The goal I create this is to delete *.bak file more then 30 days without any issue on long path and file name. Anyone got simplify solution for this?
You're going to slap yourself. The problem is that in a batch file, for loop variables need a double percent. %%A and %%~sA.

nested forfiles: path and extension filter

is there any possibility to nest two forfile commands so that I can filter by pathname and by extension and then run a command only on those double filtered files?
By example I'd like to get all Outlook HTML-signatures of all users. I can do this by
forfiles /s /p c:\Users /m *Signatures* /c "cmd /c forfiles /s /p #path /m *.htm"
But this will only display the filenames because it's the default behavior of forfiles to call cmd /c echo #file.
Changing this doesn't work because then I'd need to set the /c-option in the inner forfiles command which requires to set the command in quotes resulting in double quotes:
forfiles /s /p c:\Users /m *Signatures* /c "cmd /c forfiles /s /p #path /m *.htm /c "cmd /c echo #path""
How can I escape the inner quotes or use some different approach to run any command on all files filtered by a substring of path and the file extension?
Kind regardssc911
[edit] forgot /s for recursive searching [/edit]
Instead of forfiles you can use two nested FOR commands.
see the following one-liner example to test in a cmd prompt
#for /d %d in (c:\Users\*signature*) do #for %f in (%d\*.htm) do #echo %f
and use this code as a skeleton to include in a BAT file
for /d %%d in (c:\Users\*signatures*) do (
for %%f in (%%d\*.htm) do (
echo %%f
)
)
FORFILES seems to be able to recognise \" as the way of escaping inner ". So, the following should work:
forfiles /p c:\Users /m *Signatures* /c "cmd /c forfiles /p #path /m *.htm /c \"cmd /c echo #path\""

Resources