1

We have a backup directory that could have a folder structure up to 4 folders deep. Backups are automatically purged dependant on a sucessfull backup. The issue is that sometimes the backup routine falls over and we don't know that it has and no files are being backed up in some of the folders.

Can anyone shed some light on a script to be run via a batch file that would:

1) loop through all the folders 2) provide a list of all files that are older than 3 days 3) have the ability to state the file or folder names to be excluded from the report.

Thanks in advance,

Jonathan

Ross Ridge
  • 38,414
  • 7
  • 81
  • 112
Jonathan
  • 11
  • 1
  • 3
  • Parts 1 and 2 can be done with `forfiles.exe`. Part 3 needs further explanation how you plan to provide the files and folder names. – foxidrive Sep 30 '14 at 08:13
  • Do you want an answer that works on the old 16-bit MS-DOS operating system or a modern version of Windows? – Ross Ridge Sep 30 '14 at 17:31
  • @foxdrive, I was thinking of having a section in the batch file where the folder or file name was stipulated (perhaps with full UNC path), the script would then ignore that file or folder when outputting the report. – Jonathan Sep 30 '14 at 22:36
  • @Ross Ridge - I am using Windows 7 – Jonathan Sep 30 '14 at 22:38
  • I have got this far: `FORFILES /p N:\ /m *.* /s /c "cmd /c echo @path@file" /D -3 >> c:\temp\output.txt` The issue is in the directory and the children directories are many files that are more than 3 days old which are to be kept for archival purposes, however they are reported in the output file which makes it very difficult to see which files are 'genuinely' 3 days old or older which need to be investigated. – Jonathan Sep 30 '14 at 23:18

1 Answers1

1

You can pipe the FORFILES result to FINDSTR with the /V and /G:file options to filter out the files you want to ignore. You can embed the files to ignore directly in your batch script. The full path of each file should be used, with enclosing quotes to match the FORFILES output.

I use the /L option to force the search to use literal strings, the /X option to make sure the filter uses an exact match, and the /I option to make it case insensitive.

Note that @path represents the full path, including the file name. So @file is not needed.

Also, FORFILES will list folders, so you should exclude them using @ISDIR

@echo off
forfiles /p n:\ /m * /s /c "cmd /c if @isdir==FALSE echo @path" /d -3 | findstr /vixlg:"%~f0" > c:\temp\output.txt
exit /b

"n:\somePath1\someFileToIgnore1.ext"
"n:\somePath2\someFileToIgnore2.ext"
etc.

If you want to exclude all files within a specific folder, then you will need to modify the above script to use regular expressions, using \R instead of \L. You can construct a regular expression to specify a specific file, all files within a specific folder, or all files within a folder tree.

Backslash literals must be escaped as \\, and period literals escaped as \.. Excluding files within a folder uses [^\\]* to represent the files - it matches any string of characters except except backslash. Excluding a folder tree uses .* to match any string of characters to match both folders and files.

@echo off
forfiles /p n:\ /m * /s /c "cmd /c if @isdir==FALSE echo @path" /d -3 | findstr /vixrg:"%~f0" > c:\temp\output.txt
exit /b

"n:\\somePath1\\someFileToIgnore1\.ext"
"n:\\somePath2\\ignoreFilesInThisFolder\\[^\\]*"
"n:\\somePath3\\ignoreFilesInThisFolderTree\\.*"
etc.
dbenham
  • 127,446
  • 28
  • 251
  • 390
  • Thanks @dbenham, Ideally I would want to exclude entire directories (and all the files in them) as well as some files. For example: N:\sets\folder_1 N:\sets\folder_2\ N:\sets\zip.zip In the above example I would want to exclude the entire folder_1 directory and also the zip.zip file, but listing all the files older than 3 days in folder_2 – Jonathan Oct 01 '14 at 05:28
  • Oops, I had a bug - I forgot to include the \L option to specify a literal search. But if you want to exclude entire folders, then you need to do use regular expressions. Answer has been updated. – dbenham Oct 01 '14 at 12:09
  • Hi @dbenham, Thanks. When I run it I get the following message "The process tried to write to a nonexistent pipe" – Jonathan Oct 01 '14 at 22:47
  • @Jonathan - I can't imagine why it is failing for you. I've tested and it works fine for me. – dbenham Oct 02 '14 at 01:10
  • Hi @dbenham, Are you running the exact same syntax as what you posted? – Jonathan Oct 02 '14 at 01:13
  • @Jonathan - Yes. I changed the FORFILES path and file mask, and the FINDSTR exclusion files/folders, and the output file - all to work with my file system. But the overall syntax is exactly as shown. I notice you are walking the entire N: drive with FORFILES. I wonder if you have access to all the folders on that drive? I don't know what FORFILES does if it runs into a folder it cannot recurse into. Perhaps that could cause problems, but that is just a wild guess. – dbenham Oct 02 '14 at 01:42
  • Hi @dbenham, Thanks. I tried logged into my local machine with no luck and then logged in as the admin on the server with still the same result. Strange. – Jonathan Oct 02 '14 at 22:40
  • Hi @dbenham, I have had another crack at this. The error being reported is: `FINDSTR: Cannot Read Strings from %~f0` Any further ideas? – Jonathan Oct 08 '14 at 04:34
  • @Jonathan - `%~f0` should expand to the full path of the currently executing script. Perhaps the pipe process does not have access to the script file - but I'm not aware of anything that can cause this. The only other possibility is your `%~f0` value could be corrupted. There are some obscure situations (CMD bugs) that can lead to this unfortunate behavior. See http://stackoverflow.com/q/19781569/1012053 for more info. Toward the bottom of http://stackoverflow.com/a/19790398/1012053 I have a `:CurrentScript` routine that reliably returns the full path to the currently executing script. – dbenham Oct 08 '14 at 10:46
  • Not exactly related to the OP, but be careful when using the /P option. The command `forfiles /p n:\ /m * /s /c "cmd /c if @isdir==FALSE echo @path" /d -3` will work, but if the path contains spaces and you had this: `forfiles /p "n:\Some Path\" /m * /s /c "cmd /c if @isdir==FALSE echo @path" /d -3` you will receive `ERROR: Invalid argument/option - '@isdir==FALSE'.` - becaise the trailing \ in the path causes the closing double-quote in `"n:\Some Path\"` to be escaped and not seen by the parser. It cost me a bit of time chasing the error. Solved by removing the trailing \ – rossmcm Jul 09 '22 at 09:31