Find files through 1 folder with lots of subfolder levels and delete

Using a script, I want to delete the .xml files if a .zip file with same name is not present. The folder structure is as follow, 1 main folder/1000s of subfolders/12s of subfolders/xml and zip files…

Having said that, the following script is one I found that works perfectly when the xml and zip files are in the main folder… It cannot look through any subfolders…

I’m hopping someone will find me the solution script to do so!

Thanks in advance,
Sincerely,
Michel

Here’s the script I’m talking about,

set ff to choose folder
set ffText to ff as text

script s
property everyFileName : missing value
end script

set inTime to current date
tell application “System Events”
set s’s everyFileName to name of files of ff
end tell

repeat with aName in s’s everyFileName
if (text -3 thru -1 of aName) is “xml” then
if (text 1 thru -4 of aName & “zip”) is not in s’s everyFileName then
tell application “System Events” to delete file (ffText & aName)
end if
end if
end repeat

set s’s everyFileName to missing value

set totalTime to (current date) - inTime
return totalTime

Welcome to the forum.

What happens if a searched folder contains an .xml file but not a similarly-named zip file, but another searched folder does contain a similarly-named zip file? Should the .xml file be deleted?

Hi peavine,
Thanks for your fast reply!

The scenario you are stating should not happen and if it did, I would still want to delete it…
So the answers YES!

Thanks,
Michel

here’s a solution using AppleScriptObjC:

use AppleScript version "2.5" -- macOS 10.11 or later
use framework "Foundation"
use scripting additions

set ff to choose folder
-- get all files
set fileManager to current application's NSFileManager's new()
set theFiles to (fileManager's enumeratorAtURL:ff includingPropertiesForKeys:{} options:((current application's NSDirectoryEnumerationSkipsPackageDescendants) + (current application's NSDirectoryEnumerationSkipsHiddenFiles as integer)) errorHandler:(missing value))'s allObjects()
-- get names of .zip files
set thePred to current application's NSPredicate's predicateWithFormat:"pathExtension == 'zip'"
set zipFiles to theFiles's filteredArrayUsingPredicate:thePred
set zipFileNames to zipFiles's valueForKeyPath:"lastPathComponent.stringByDeletingPathExtension"
-- get .xml files whose names aren't in above
set thePred to current application's NSPredicate's predicateWithFormat:"(%K == %@) AND  NOT (%K IN %@)" argumentArray:{"pathExtension", "xml", "lastPathComponent.stringByDeletingPathExtension", zipFileNames}
set xmlFiles to theFiles's filteredArrayUsingPredicate:thePred
-- delete the files
repeat with afile in xmlFiles
	-- delete immediately
	(fileManager's removeItemAtURL:afile |error|:(missing value))
	-- or move to trash
	(fileManager's trashItemAtURL:afile resultingItemURL:(missing value) |error|:(missing value))
end repeat

If the answer were no, you could modify the above by changing the two instances of lastPathComponent to simply path.

I think you mean xmlFiles and .xml.

More importantly, find will look inside bundles, and .xml files (and .html files) are very common in things like app bundles. So the script as it stands, with the last two lines uncommented, could do quite a bit of unintentional damage.

Thanks Shane. I’ll delete my script.

Hi Shane,
I tried your script on a test folder I created and the following error came up…

error “NSFileManager doesn’t understand the “new” message.” number -1708 from NSFileManager

Just so we are on the same page, I don’t want the script to look inside any file, I just want it to go through folders and subfolders and find .xml files that is not match with the same name .zip file…
The folders containing the 2 kind of files don’t contain any other type of files…

Hope I explain this properly…

Input will be greatly appreciated!
Thanks,
Michel

That’s the error that occurs if you leave off the use framework “Foundation” statement. Are you sure you’re running the whole script as posted?

Right.

Hi Shane,

It was my mistake… I apologize for the confusion…

WOW, IT WORKS PERFECTLY!

Greatly appreciate your help!
Thanks everyone,
Michel