How to Delete Files that Have the Same File Name as Other Files with a Different File Type?

Purpose: Delete all PDF/PostScript files that have same FileName with TXT files

There are 9000+ files, 800+ is PDF and PostScript FileType

I found these discusses still have no idea how to store FileName.

I'm unclear about what you want...

You only want to delete PDF/PS files that have an analogous text file?

There might be PDF/PS files that don't have an analogous text file?

Do you care whether you use Keyboard Maestro native actions or AppleScript?

Yes, I want delete PDF/PS files that have an analogous text file and keep PDF/PostScript files that don't have an analogous text file.

I'm grateful if any method works.

I haven’t writing macro for too long even forget how to use variable.

This is my draft for now:

Delete Different FileType with same FileName.kmmacros (5.2 KB)

Run this for me in Apple's Script Editor (or Script Debugger if you have it):

--------------------------------------------------------
use AppleScript version "2.4" --» Yosemite or later
use framework "Foundation"
use scripting additions
--------------------------------------------------------
property posixPath : "~/Documents/ccs.xxx/"
--------------------------------------------------------

set posixPath to ((current application's NSString's stringWithString:posixPath)'s stringByExpandingTildeInPath) as text

return alias POSIX file posixPath

--------------------------------------------------------

I need to know if it throws an error.

It will on my system (Mojave), but Apple made some changes later on – and I need to know if a certain technique still works.

1 Like

It works on macOS Ventura 22A5373b (Latest Public Beta)

--------------------------------------------------------
use AppleScript version "2.4" --» Yosemite or later
use framework "Foundation"
use scripting additions
--------------------------------------------------------
property posixPath : "~/Documents/orwell-1984.chm/"
--------------------------------------------------------

set posixPath to ((current application's NSString's stringWithString:posixPath)'s stringByExpandingTildeInPath) as text

return alias POSIX file posixPath

--------------------------------------------------------
alias "Macintosh HD:Users:suliveevil:Documents:orwell-1984.chm"

This question is exactly what I'm expected to do:

Those methods look like they'll be effective, although the more files you have the slower the Finder grinds when using AppleScript.

So I'd probably use a somewhat different method – unless I elected to use the shell script.

1 Like

Shell script is dangerous for users who are not a programmer like me, but it is powerful though difficult to understand. :joy:

1 Like

Delete pdf&ps file only if the txt exists:

for f in *.pdf; do [[ -e ${f%pdf}txt ]] && rm "$f"; done
for f in *.ps; do [[ -e ${f%ps}txt ]] && rm "$f"; done
1 Like

Did you try this?

If so – how long did it take?

Would you mind running the AppleScript I asked you to run and letting me know whether it errors or not?

And would you mind telling me what version of macOS you're running? It would help me out in future.

-Chris

The shell script is pretty fast under 1 second or so working on deleting 800+ files from 9000+ files.

Your AppleScript works:

DRAT!

It should throw an error, because that alias does not exist – but Apple changed the way aliases work in in Catalina (if I remember correctly).

With Catalina forward you can create an alias to an item that does NOT exist – and this changes the behavior aliases have had for decades.

That's a bummer, because you could use the old behavior to coerce a path to an alias and test if a file or folder exists in less than 0.001 seconds...

Now I'll have to learn how to use AppleScriptObjC and the File Manager to test for an item's existence – that should be way faster than using either the Finder or System Events.


Wow!

I ran the shell scripts on a test folder with 12,000 files where 36 files where of type .ps and 36 were of type .pdf and the rest were text files.

prompt> time for f in *.pdf; do [[ -e ${f%pdf}txt ]] && rm "$f"; done

real	0m0.173s
user	0m0.062s
sys	0m0.087s

prompt> time for f in *.ps; do [[ -e ${f%ps}txt ]] && rm "$f"; done

real	0m0.168s
user	0m0.058s
sys	0m0.084s

Even on my old i7 MacBook Air this is most impressive.

By contrast – my fairly well optimized AppleScript takes almost a minute to run.

3 Likes

AppleScript is not as good as those Unix tools in manipulating strings and files, it's suitable for GUI Scripting and cross-App communication.

Vanilla AppleScript is very good and very fast at working with strings – up to a point – and if you know what you are doing.

AppleScriptObjC has full regular expression support and many other tools – but it is not so easy to learn.


Vanilla AppleScript works very well manipulating files and folders depending upon what you're doing and how many items you're working with (and your skill level).

AppleScriptObjC is very powerful and very fast – but again – not so easy to learn.


** It is somewhat silly these days to separate vanilla AppleScript from AppleScriptObjC – because ASObjC has been around since macOS 10.6 (2009) and fully available to users since macOS 10.10 (2014).


And then there's JavaScript for Automation – which has its own impressive array of tools.


Traditional Unix shell tools sometimes have problems with Unicode – despite the fact that Unicode has been with us since 1991.

That said – the shell and its tools are still very powerful and useful – when you know what you're doing.

I'd bet a beer that an AppleScriptObjC version of this delete files script wouldn't be as fast, and I know it would be more difficult to write.

2 Likes

I wrote some scripts years ago, re-learn forgotten skills is too hard especially when lack of newest tutorials and books, official Docs is archived, scripts broken between macOS versions.

Interesting challenge.

If you prefer a GUI, you could do this also with my $6 shareware app (you can test it without paying first) Find Any File. And with its new feature of writing custom rules in Lua or JavaScript (currently only in the beta version).

The found items would then be shown in a Finder-like window, from where you can select and delete or trash or move them as you like.

If you are interested (I like the challenges and always look for more uses and improvements for FAF), I can make a script for the rule you need.

And you can also invoke FAF from KM, and pass parameters (e.g. the filename) to it if you like.

3 Likes

Thank you for sharing your thoughts, I'm satisfied with the current solution.

1 Like

Don't worry, it does throw an error. The only reason it didn't for @suliveevil is because s/he edited the value of the property declaration for posixPath (to that of a path that presumably exists).

I don't know the method for doing this? How does one do it?

As far as I know, that method should still work. If it doesn't, you can coerce it to «class fsrf» instead, which will fail if the path doesn't exist. It's very much like alias except that it doesn't take HFS paths. Therefore, the file reference returned by «class fsrf» doesn't need POSIX file to serve as an intermediary, however it's also strictly a type class so cannot be invoked as a specifier.

This is the method I use that hasn't needed changing since its inception back in High Sierra, and still works on Monterey:

on fileExists at path as text
    if the path's length = 0 then return false
    path's POSIX path as {«class fsrf», anything}
    the result's class ≠ text
end fileExists
1 Like

Crud. I totally missed that – thanks for pointing it out.

Hmm...

Perhaps I misremember the behavior Shane described on the Script Debugger Forum.