Need BIG help... Accidentally corrupted a folder using KM

bug
km8

#1

Guys, I’m taking any help.

I accidentally created a file using the action “Write to a File” using blank variables for name and extension and the folder the file was in is now corrupted (reads as zero bytes and kind is TextEdit).

The file created was VarName1.VarName2 and both variables were empty.

Anyway to revert it? I had hundreds of files from work inside that folder…


#2

Unfortunately, it appears that Apple’s NSFileWrapper writeToURL:options:originalContentsURL:error: API call will, if given the path to a directory, overwrite the entire directory with the file. This is really bad behaviour for an API, and I have reported it to Apple. I will defend against this case in the next version of Keyboard Maestro.

The destroyed directory is deleted as far as I can tell, so the only way to restore it is from your backups unfortunately.


#3

@gustavomd, can you please post your macro that caused the problem?
It seems to me that IF you used KM Variables that were empty, then the KM Action should have failed, rather than overwrite something.

See KM Wiki: How to Post/Upload Your Macro to the Forum


#4

@gustavomd, no need to upload your macro. I have confirmed this terrible behavior.

@peternlewis, thanks for confirming this bad behavior.
Can you please make a KM update ASAP to fix?
Thanks.

Here’s my test macro, for use ONLY by @peternlewis.

This macro will DESTROY the last FOLDER in the path

MACRO:   Attempt to Write to File with Empty Variables – DO NOT USE

~~~ VER: 1.0    2018-02-12 ~~~


image


#5

Do not mess around with this without being very careful. Basically, if you specify an existing directory (or ~/existingdirectory/. (which is what @gustavomd did inadvertently), the system API will overwrite the entire directory and replace it with a file. It is a very nasty bug. I have reported it to Apple.


#6

@peternlewis, I totally agree. There is no reason for anyone to use my TEST macro above.

However, I have found an AppleScript ASObjC solution that does NOT have this issue. It will write ONLY to a file, and will NOT overwrite a Folder. But it DOES overwrite an existing file that has the same path.

Example Output

If Error (Not Successful)

image

If Successful

image


MACRO:   Write to File Using AppleScript [Example]

~~~ VER: 1.0    2018-02-12 ~~~

DOWNLOAD:

Write to File Using AppleScript [Example].kmmacros (14 KB)
Note: This Macro was uploaded in a DISABLED state. You must enable before it can be triggered.


###ReleaseNotes

Author.@JMichaelTX

PURPOSE:

  • Write String to File, ensuring that a Folder is NOT overwritten.
    • Use this instead of the KM Action Write File which WILL overwrite a folder if an improper filePath is provided.

REQUIRES:

  1. KM 8.0.2+
  • But it can be written in KM 7.3.1+
  • It is KM8 specific just because some of the Actions have changed to make things simpler, but equivalent Actions are available in KM 7.3.1.
    .
  1. macOS 10.11.6 (El Capitan)
  • KM 8 Requires Yosemite or later, so this macro will probably run on Yosemite, but I make no guarantees. :wink:

NOTICE: This macro/script is just an Example

  • It has had very limited testing.
  • You need to test further before using in a production environment.
  • It does not have extensive error checking/handling.
  • It may not be complete. It is provided as an example to show you one approach to solving a problem.

HOW TO USE:

  1. Set the first four KM Actions according to your needs:
  • Local__FileName
  • Local__FileExt
  • Local__FilePath
  • Local__FileContents
    .
  1. Trigger this macro

MACRO SETUP

  • Carefully review the Release Notes and the Macro Actions
    • Make sure you understand what the Macro will do.
    • You are responsible for running the Macro, not me. :wink:
      .
  • Assign a Trigger to this maro.
  • Move this macro to a Macro Group that is only Active when you need this Macro.
  • ENABLE this Macro.
    .
  • REVIEW/CHANGE THE FOLLOWING MACRO ACTIONS:
    (all shown in the magenta color)

TAGS: @Files @WriteFile @AppleScript

USER SETTINGS:

  • Any Action in magenta color is designed to be changed by end-user

ACTION COLOR CODES

  • To facilitate the reading, customizing, and maintenance of this macro,
    key Actions are colored as follows:
  • GREEN – Key Comments designed to highlight main sections of macro
  • MAGENTA – Actions designed to be customized by user
  • YELLOW – Primary Actions (usually the main purpose of the macro)
  • ORANGE – Actions that permanently destroy Variables or Clipboards,
    OR IF/THEN and PAUSE Actions

USE AT YOUR OWN RISK

  • While I have given this limited testing, and to the best of my knowledge will do no harm, I cannot guarantee it.
  • If you have any doubts or questions:
    • Ask first
    • Turn on the KM Debugger from the KM Status Menu, and step through the macro, making sure you understand what it is doing with each Action.

image


AppleScript

property ptyScriptName : "Write String to File"
property ptyScriptVer : "1.0"
property ptyScriptDate : "2018-02-12"
property ptyScriptAuthor : "JMichaelTX"

use AppleScript version "2.5" -- El Capitan (10.11) or later
use framework "Foundation" -- this may not be required
use framework "AppKit" -- this may not be required
use scripting additions

property LF : linefeed

### Requires Keyboard Maestro 8.0.3+ ###

set kmInst to system attribute "KMINSTANCE"

tell application "Keyboard Maestro Engine"
  set filePath to getvariable "Local__FilePath" instance kmInst
  set fileContents to getvariable "Local__FileContents" instance kmInst
end tell

set successBool to my writeFile(filePath, fileContents)

if (successBool) then
  set msgStr to "File was SUCCESSFULLY written to:" & LF & ¬
    filePath
  return "OK" & LF & msgStr
  
else
  
  set msgStr to "Unable to Write to File, most likely due to invalid file path." & LF & ¬
    "File Path:" & LF & ¬
    filePath
  set titleStr to ptyScriptName
  
  display dialog msgStr ¬
    with title titleStr ¬
    buttons {"OK"} ¬
    with icon stop
  
  return "[ERROR]" & LF & msgStr
  
end if

--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
on writeFile(pPosixPath, pStringToWrite)
  -----------------------------------------------------
  
  set anNSString to current application's NSString's stringWithString:pStringToWrite
  set posixPath to (current application's NSString's stringWithString:pPosixPath)'s stringByExpandingTildeInPath
  
  anNSString's writeToFile:posixPath atomically:true encoding:(current application's NSUTF8StringEncoding) |error|:(missing value)
end writeFile


#7

Yes, but it only writes text, the action can write various different styles, most particularly in this case Styled Text which is what the less commonly used NSFileWrapper API is for.


#8

Thank you for the thorough feedback @peternlewis and @JMichaelTX!
KM is awesome and coupled with this community makes it really the best.

I have restored a time machine backup from a few days ago (last time I was on my home wifi). Dropbox didn’t help since the affected folder was instantly synced to all my devices.

I’ll pause Dropbox next time I’m testing new macros.

You guys all be good.


#9

I believe this is fixed in Keyboard Maestro 8.1.1.

To be clear, the folder is replaced with a file by the same name (but no extension), but now, with Ver 8.1.1, the folder is moved to the macOS Trash, so it can be recovered.

However, there is no notice that the folder is being overwritten.

@peternlewis, the behavior with 8.1.1 is better, but still leaves much to be desired. IMO, you should should do the following:

  1. Always provide a warning if a folder will be replaced with a file, and vice-versa.
  2. Provide an optional setting in the Action gear menu to provide a warning if the file already exists.

The behavior of the Write to File action is inconsistent with the Move File action. The Move File action will fail if the file already exists.

IMO, both of these should have the same behavior with respect to replacing an existing folder/file.


#10

Yeah, I lost a lot of work files. It’s bad, but recoverable. Now imagine losing all your pictures…


#11

Absolutely - if you haven’t got a backup system in place, stop typing and go buy a harddisk and set one up.

Then after that, start thinking about a real backup system, go and buy another couple harddisks, and start rotating them off-site (parents/childs/friends/whatever).

This applies whether you use Keyboard Maestro or not, because there are many ways to lose your files, many that require a lot less bad luck than a crap Apple API (which Apple says is “working as designed” BTW) or a misconfigured macro.


#12

Best advice on the whole thread. Thanks Peter!


#13

Hey @gustavomd,

I’ve gotten hosed now and then over the 34 years I’ve been using Macs when writing files in various ways.

My rule-of-the-thumb after all that “experience” is to always test macros/scripts that can write files in a test folder far away from anything critical. (I have a little thumb drive devoted to that sort of thing.)

This gnarly API issue isn’ t unique by any means. I had my whole Downloads folder wiped out some years ago by an AppleScript with a mangled path that errantly targeted the folder instead of a given file contained within it.

I was fortunate to have a recent backup.

Every computer user will have at least one data disaster (generally more than one). It’s best to be prepared.

-Chris


#14

That should be a warning message when you first open Keyboard Maestro. This is a definite “Here there be dragons” kind of application.