How to test whether a specific file exists

Is it possible with Keyboard Maestro whether a specific file exists in a specific location?

For example, as part of a macro I would like to know whether:

  1. “file.wpd” exists at /home/victor/wpdocs/; and
  2. all files start with the filename “file” exist.

And then to delete the file or files (depending on whether it is 1. or 2.). If 2. would I need to use a For Each Item action?

Any help would be gratefully received.

1 Like

You can have a look to:
https://wiki.keyboardmaestro.com/condition/Path

– Alain

1 Like

Hey Victor,

Of course.

There is no such test in Keyboard Maestro.

You have to test each file and/or folder in a directory for a name condition and then process based on the test.

Something like this:

For Each.kmactions (3.0 KB)

Instead of displaying the file name and file path you'd delete the file.

This is a little easier to do with AppleScript if you know how.

set targetFolder to path to downloads folder

tell application "Finder"
  set myFinderItems to (files of targetFolder whose name starts with "file") as alias list
  if myFinderItems ≠ {} then
    delete myFinderItems # files are moved to the trash.
  else
    beep
  end if
end tell

But. If there are many, many files/folders in the target directory it can be slow.

Faster yet is to use the shell:

#! /usr/bin/env bash

cd ~/"Downloads/untitled folder/";
rm file*; # files are instantly deleted.

But. You really need to know what you're doing.

-Chris

1 Like

Thank you the replies. Before I saw Chris' reply I worked out how to delete any file containing containing 'file' in the filename

However I can see from Chris' version what is necessary to capture just the filename, although matching "^file" does not match any files at all, and not just the files starting with "file'. However, the following appears to do the job:

Since this is all new to me, if there is anything wrong in the macro I would grateful to know.

Hey Victor,

Sure it does. I test every macro I post.

(Tested with Keyboard Maestro 7.0.4d2 on OSX 10.11.3.)

The pattern is case-sensitive though. To make it case insensitive:

(?i)^file

In your first macro you're searching to see if the entire path contains “file”.

That is potentially VERY dangerous.

Suppose one folder-name in the path is “file” or contains “file”:

~/yourUser/To Be Filed/Jpeg Folder/

You could wipe out a bunch of files you didn't intend to delete.

You could use a regular expression to safely test against the full file-path, but it's less complicated (and therefore safer) to test the file-name instead.

You have two tests:

A) ^file(.+)\.wpd$
B) fileName contains “file.wpd”

This is not wrong, but it's more complicated than necessary. Also “contains” is a far cry from “starts with”.

By changing your regular expression slightly you can narrow that down to 1 test:

^file(.*)\.wpd$

The asterisk indicates zero or more instead of the plus sign's 1 or more.

My original pattern (^file) should work. If it is in fact NOT working then something is very strange.

However – ^file(.*)\.wpd$ is a much safer pattern to use if you want to restrict delete files to WordPerfect documents.

-Chris

1 Like

Chris,

Thank you for your post. Apologies I was not clear enough in my previous post: I meant ^file was not working for me yesterday. Today I tried again and it worked. I only tried the other regex expressions because ^file was not working.

I agree entirely that a contain statement is potentially highly dangerous (if combined with a delete file command). However, the folder (for me) is only used for one specific purpose and normally contains only a file starting with “file”.

Thank you for the further regex examples.

Also, to reduce the danger, unless there is some particular reason not to, I would recommend using Trash instead of Delete - the file will be moved to the trash, and can then be emptied at some later date (personally, I only empty my trash about once per year).

2 Likes

Hello Peter, After the new update to Version 7.2 this is not working now? and was working with recent version…

tell application "Keyboard Maestro Engine"
   set kmVarRef to make variable with properties {name:"pathStr"}
   set target_folder to value of kmVarRef
end tell
--usage: wc [-clmw]
set numberOfFiles to do shell script "find " & (quoted form of POSIX path of target_folder) & " -type f |wc -l  "

Best Regards,
William Mabey 

Bill,

I don’t know if this is related to your issue, but since KM 7.1 you can get the value of a KM variable with this simple statement:

tell application "Keyboard Maestro Engine" to set target_folder to getvariable "pathStr"

Hey Bill,

What you’re doing there is (potentially) dangerous, because if the variable doesn’t exist it is created without a value.

--------------------------------------------------------------------------------
tell application "Keyboard Maestro Engine"
   
   if not (variable "pathStr" exists) then
      setvariable "pathStr" to "default value"
   end if
   
   set target_folder to getvariable "pathstr"
   
end tell
--------------------------------------------------------------------------------

Since getVariable will return a empty string “” if a variable does not exist, you could write it this way:

--------------------------------------------------------------------------------
tell application "Keyboard Maestro Engine"
   
   set target_folder to getvariable "pathstr"
   
   if target_folder = "" then
      set target_folder to "default_value"
      set target_folder to getvariable "pathstr"
   end if
   
end tell
--------------------------------------------------------------------------------

The former is a little better style, because it explicitly checks for the existence of the variable, and this is easier to read and understand than the implicit check in the second script.

It’s up to you to make sure your variables contain the correct data, before you call commands that depend on them.

In this one I’ve added an awk command to strip the whitespace off of the final value.

--------------------------------------------------------------------------------
tell application "Keyboard Maestro Engine" to set target_folder to getvariable "pathStr"

if target_folder ≠ "" then
   
   if target_folder starts with "~" then
      tell application "System Events" to set target_folder to POSIX path of disk item target_folder
   end if
   
   if target_folder starts with "/" then
      set numberOfFiles to do shell script "find " & (quoted form of POSIX path of target_folder) & " -type f \\( ! -name '.DS_Store' \\) | wc -l | awk '{print $1}'"
   end if
   
else
   error "Something is wrong with the value of variable ‘pathStr’!"
end if
--------------------------------------------------------------------------------

-Chris

EDIT: Last script in above post modified to prevent inclusion of .DS_Store files.

-Chris

“not working” is really not very helpful - what error is produced? There are multiple parts to the script, what parts are working, what parts are not?

“POSIX path of target_folder” does not make any sense. target_folder is a string variable, it has just plain string in it, which presumably already is a posix path. “POSIX path” is used to return a path in a specific format from an object like an alias or file reference.

Sorry I was so exhausted.. :confounded:

It's working fine now, I rebooted the Mac... I should Have done this first.. anyways here is the Macro.



Check and clean Anime Studio files.kmmacros (4.4 KB)



@ccstone Should I replace the script with this one?


tell application "Keyboard Maestro Engine" to set target_folder to getvariable "pathStr"

if target_folder ≠ "" then

if target_folder starts with "~" then
tell application "System Events" to set target_folder to POSIX path of disk item target_folder
end if

if target_folder starts with "/" then
set numberOfFiles to do shell script "find " & (quoted form of POSIX path of target_folder) & " -type f \( ! -name '.DS_Store' \) | wc -l | awk '{print $1}'"
end if

else
error "Something is wrong with the value of variable ‘pathStr’!"
end if


Best Regards,
William Mabey 