Find and Replace text in macros

Is there a way to search and replace text within multiple macros? For instance, I work with a team that uses a lot of the same macros. Another person created 30 macros that I want to use involving file system directions (⌘⇧G followed by the folder name) So, I would want KM to search for all instances of the word “xxxxx” and replace it with the word “zzzzz.”

Hey Jeremy,

Not in the Keyboard Maestro Editor.

You can export the macros – do a find/replace in the XML files – and then reimport them.

TextWrangler (or BBEdit) will let you do a multi-file search/replace.

This is not simple, but it's doable.

In general macros accessing the file-system should use relative paths for portability.

So instead of:

/Users/your-user/Downloads/your-file.txt

You'd use:

~/Downloads/your-file.txt

There are Expand Tilde in Path and Abbreviate Tilde in Path filters.

The OSX Go-To pop-up menu understands $HOME-Notation paths (e.g. ~/).

Keyboard Maestro also understands that notation in fields that require a path.

-Chris

Bummer. That’s a bigger pain than just manually pasting in the new file field.

I for one would like to see a search/replace function show up in the Keyboard Maestro editor.

I know that’s a whole lot easier said than done though.

-Chris

Hi, just found this post after wondering the same thing. I upgraded my Dropbox account to Business and the service decided it would be a good idea to append the team name to the Dropbox folder without allowing me to change it back to simply Dropbox/

I have hundreds of macros that reference files in Dropbox directories. Also, I have links and scripts that trigger my macros from other applications (like OmniFocus). Presumably, exporting and reimporting all of my macros would change these unique macro IDs, right? And would I lose my folder structure of all my macros?

Is there a file inside KM’s Application files I can jump into to do a find/replace or would this mess things up?

Thanks in advance!

You might try creating a Symlink for "Dropbox" that points to your "Dropbox Team" folder. Put the Symlink in the same folder as the original "Dropbox" folder that is referenced by your Macros.

I have a script that will create the Symlinks. You can put this script in a KM Action "Execute AppleScript", run it from Script Editor, or put in the ~/Library/Scripts/Applications/Finder folder that the Apple Script menu uses.

Select the Original Item in the Finder,
and trigger this script.


use AppleScript version "2.4"
use framework "Foundation"
use scripting additions


tell application "Finder"
  
  --- GET LIST OF ORIGINAL ITEMS ---
  set itemList to the selection as alias list
  set numItems to count of itemList
  
  --- ASK USER WHICH LINK TYPE TO CREATE ---
  
  set msgStr to "Links to be Created for All Items Selected in Finder" & return & "Number of Items: " & numItems
  
  set ansRec to display dialog ¬
    msgStr buttons {"Cancel", "Alias", "Symlink"} ¬
    default button ¬
    "Symlink" cancel button ¬
    "Cancel" with title ¬
    "Create Symlink OR Alias?" with icon caution
  
  set linktype to button returned of ansRec
  
  --- GET THE LOCATION WHERE TO PUT THE LINK ---
  
  set targetFolderAlias to choose folder with prompt ¬
    "Select DESTINATION Folder for Symlink" default location (path to library folder from user domain)
  set targetFolderPath to POSIX path of targetFolderAlias
  
  --log targetFolderPath
  
  --- PROCESS ALL ITEMS IN FINDER SELECTION ---
  
  repeat with itemAlias in itemList
    
    --- Original Item ---
    set itemPath to POSIX path of itemAlias
    --log itemPath
    
    --- ASOBjC Needs Full Path of Symlink ---
    set linkName to (name of itemAlias)
    set linkPath to targetFolderPath & linkName
    
    if (linktype = "Symlink") then
      -----------------------------
      --- CREATE SYMLINK ---
      -----------------------------
      
      --- BASED ON SCRIPT BY @Tom & @koenigyvan ---
      set {successBool, nsError} to ((current application's NSFileManager's defaultManager())'s createSymbolicLinkAtPath:linkPath withDestinationPath:itemPath |error|:(reference))
      
      if not (successBool as boolean) then error (nsError's |localizedDescription|() as text)
      
      --- ALTERNATE METHOD BASED ON SCRIPT BY @Tom ---
      --  Testing showed ASObjC method to be faster
      --    do shell script "ln -s" & space & quoted form of itemPath & space & quoted form of targetFolderPath
      
    else
      -----------------------------
      --- CREATE ALIAS ---
      -----------------------------
      
      make new alias at targetFolderAlias to item itemAlias with properties {name:linkName}
      
    end if -- linktype
    
  end repeat -- "itemList"
  
end tell -- "Finder"

1 Like

Holy moly you just exploded by brain (but don’t worry, I can mop it up using all the hours you just saved me). I have to test more but this seems to be exactly what I needed!

Thanks and great job on that script!!

Cheers,

Joel

1 Like

I would really like to see proper search & replace too.

What about an option for the editor to 'open in text view', then the main editor window shows plain text rather than the graphical version. Then enable a search/replace option in the menu and when we save it flips back to the normal graphic view.

That way the search/replace is only available in text view, is easy to implement and doesn't mess with the main editor.

Mark.

That would be incredibly hard to do, unless the text view was XML, in which case it would be incredibly likely that changes made would destroy the macro.

I don't suppose you could do a find/find-next within the macro?

If I find say 'myDate' then it highlights them I then have to manually go through everyone hoping not to miss any (and like I said about word search, if I replace myDate with myDateX then they all stay highlighted making it a nightmare, I am bound to miss one and it takes forever). If I could find 'myDate' and it went to the first occurrence (expanding as required) I could then do a paste to replace and then a find next to move to the next instance. That way I am sure I don't miss any and it isn't as big a problem.

Cheers,

Mark.

Maybe one day.

If I find say 'myDate' then it highlights them I then have to manually go through everyone hoping not to miss any (and like I said about word search, if I replace myDate with myDateX then they all stay highlighted making it a nightmare, I am bound to miss one and it takes forever)

A solution would be to replace myDate with myXDate, then replace myXDate with myDateX. That way the initial search for myDate would show all entries, and when you had fixed them all, the search for myXDate would find all entries until you fix them all. It means doing two passes, but does give you a reliable solution.