Create a New File in the Finder from a Selection of Templates

Hello, I'm trying to make it so if I hit a hotkey, Keyboard Maestro will create a new text file in the current Finder location.

I tried the "copy file to" function but it requires a destination location (I tried leaving the destination blank and making the next step cmd-v but it didn't work).

I am running version 6.4.7 on Mavericks. I hope somebody can help. Thanks. :slight_smile:

1 Like

Hey @emc,

That's simple, but please provide more information like:

  • What the file should be named.
  • Does it require any content?

I have a script that chooses from a folder of template files, so I can add-to or change them easily in the Finder.

I replicated the functionality of an old utility called “New Files Here!” with AppleScript.

-Chris

Hello Chris, thanks for the reply. A good name would be “Notes”. It does not require any content, but I would prefer it to be in rich text format rather than plain text. Thanks. :slight_smile:

Hey @emc,

You can’t create a RTF file out of nothing like you can a plain text file (at least with vanilla AppleScript).

But you can use a template file, and duplicate it wherever you want.

Here’s the basic AppleScript.

------------------------------------------------------------
# User's Templates Folder:
set templateFileFolder to alias ((path to application support from user domain as text) & "Script_Support:New_File_Here!:")

tell application "Finder"

  # The frontmost open folder (Desktop if no folders are open):
  set templateDestinationFolder to insertion location as alias

  # Get a reference to your RTF template file:
  set theTemplate to (first file of templateFileFolder whose name ends with ".rtf") as alias

  # Copy the template to the insertion location in the Finder:
  duplicate theTemplate to templateDestinationFolder

end tell
------------------------------------------------------------

With this you can name the RTF template anything you want (as long as the .rtf suffix is there).

If you have trouble adjusting the User’s Template Folder to your system then post the path of where you want it, and I’ll help you change it.

-Chris

Chris,

The workflow you describe (popup with list of template) is exactly what I’m looking for. Would you be willing to share your entire code here?

Thanks.

Hey Carlos,

Sure.

On first run the script will create a templates folder and a text-template. That folder will then be opened, so you can see where it lives.

All other templates must be added by the user.

The top item in the Choose-From list is “ Open New_Files_Here! folder” and does just want it says.

-Chris

---------------------------------------------------------------------------------
# Auth: Christopher Stone <scriptmeister@thestoneforge.com>
# dCre: 2012/10/26 01:27
# dMod: 2016/06/07 01:07
# Appl: Finder
# Task: Create a new file from a file-type list in the front Finder window using
#     : template files stored in a folder.
# Libs: Template files provided by the user.
# Osax: None 
# Tags: @Applescript, @New, @Files, @Here, @Create
# Note: If no templates exist a Text-Template is auto-created - user supplies others.
---------------------------------------------------------------------------------

try
   
   try
      set templateFolderPath to ((path to application support from user domain as text) & "Script_Support:New_File_Here!:")
      set templateFolder to alias templateFolderPath
   on error
      set newFilesHereFolder to quoted form of (POSIX path of templateFolderPath)
      set textTemplate to newFilesHereFolder & "Text_Template.txt"
      do shell script "mkdir -p " & newFilesHereFolder & ";
     touch " & textTemplate & ";
     open -R " & textTemplate
      return
   end try
   
   tell application "Finder"
      if front window exists then
         set winTarget to target of front window as alias
         set fileTemplateList to name of files of templateFolder
         set beginning of fileTemplateList to " Open New_Files_Here! Folder"
         set textTemplate to name of files of templateFolder whose name starts with "Text"
         
         tell me to set fileType to choose from list fileTemplateList with title "New_File_Here! Templates" with prompt ¬
            "Pick One or More:" default items {textTemplate} with multiple selections allowed
         
         if fileType ≠ false then
            if fileType = {" Open New_Files_Here! Folder"} then
               open templateFolder
               return
            end if
            
            set AppleScript's text item delimiters to (return & templateFolderPath)
            set itemsToCopy to paragraphs of ((templateFolder as text) & fileType)
            
            repeat with i in itemsToCopy
               set i's contents to i as alias
            end repeat
            
            set copiedFiles to duplicate itemsToCopy to winTarget
            select copiedFiles
         end if
         
      else
         error "No windows open in Finder!"
      end if
   end tell
   
on error e number n
   set e to e & return & return & "Num: " & n
   if n ≠ -128 then
      try
         tell application (path to frontmost application as text) to set ddButton to button returned of ¬
            (display dialog e with title "ERROR!" buttons {"Copy Error Message", "Cancel", "OK"} ¬
               default button "OK" giving up after 30)
         if ddButton = "Copy Error Message" then set the clipboard to e
      end try
   end if
end try

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

Thanks, Chris, that worked great!

1 Like

Hey Folks,

I've revised the AppleScript in post #6 to change the newly created template files' creation and modification dates to NOW() when the user creates them.

The old script leaves the dates the same as the template files.

-Chris

----------------------------------------------------------------
# Auth: Christopher Stone <scriptmeister@thestoneforge.com>
# dCre: 2012/10/26 01:27
# dMod: 2018/11/15 02:31
# Appl: Finder
# Task: Create a new file from a file-type list in the front Finder window using
#     : template files stored in a folder.
# Libs: Template files provided by the user.
# Osax: None 
# Tags: @Applescript
# Note: Auto-creates a Text template - others are for the user to supply.
# Chng: Change List is appended at end.
# Vers: 1.50
----------------------------------------------------------------
use AppleScript version "2.5"
use framework "Foundation"
use scripting additions
----------------------------------------------------------------

try
   
   -------------------------------------------------------------
   --» Ensure the New-File-Here! folder exists.
   -------------------------------------------------------------
   
   try
      set templateFolderPath to ((path to application support from user domain as text) & "Script_Support:New_File_Here!:")
      set templateFolder to alias templateFolderPath
   on error
      set newFilesHereFolder to quoted form of (POSIX path of templateFolderPath)
      set textTemplate to newFilesHereFolder & "Text_Template.txt"
      
      do shell script "
         mkdir -p " & newFilesHereFolder & ";
         touch " & textTemplate & ";
         open -R " & textTemplate
      
      return -- Bail!
      
   end try
   
   -------------------------------------------------------------
   
   tell application "Finder"
      if front window exists then
         set winTarget to target of front window as alias
         set fileTemplateList to name of files of templateFolder
         set beginning of fileTemplateList to " Open New_Files_Here! Folder"
         set textTemplate to name of files of templateFolder whose name starts with "Text"
         
         tell me to set fileType to choose from list fileTemplateList with title "New_File_Here! Templates" with prompt ¬
            "Pick One or More:" default items {textTemplate} with multiple selections allowed
         
         if fileType = false then
            
            return -- Bail!
            
         else if fileType ≠ false then
            
            if fileType = {" Open New_Files_Here! Folder"} then
               open templateFolder
               
               return -- Bail!
               
            end if
            
            set AppleScript's text item delimiters to (return & templateFolderPath)
            set itemsToCopy to paragraphs of ((templateFolder as text) & fileType)
            
            repeat with i in itemsToCopy
               set i's contents to i as alias
            end repeat
            
            set copiedFiles to duplicate itemsToCopy to winTarget
            
            if class of copiedFiles is not list then
               set copiedFiles to {copiedFiles}
            end if
            
            select copiedFiles
            
            repeat with i in copiedFiles
               set contents of i to POSIX path of (i as alias)
            end repeat
            
         end if
         
      else
         error "No windows open in Finder!"
      end if
      
   end tell
   
   set theDate to current date
   
   repeat with thePath in copiedFiles
      set theURL to (current application's |NSURL|'s fileURLWithPath:thePath)
      
      set {resultOfCreationDate, theError} to (theURL's setResourceValue:theDate forKey:(current application's NSURLCreationDateKey) |error|:(reference))
      if resultOfCreationDate as boolean is false then error (theError's localizedDescription() as text)
      
      set {resultOfModificationDate, theError} to (theURL's setResourceValue:theDate forKey:(current application's NSURLContentModificationDateKey) |error|:(reference))
      if resultOfModificationDate as boolean is false then error (theError's localizedDescription() as text)
      
      set {resultOfContentAccessDate, theError} to (theURL's setResourceValue:theDate forKey:(current application's NSURLContentAccessDateKey) |error|:(reference))
      if resultOfContentAccessDate as boolean is false then error (theError's localizedDescription() as text)
   end repeat
   
on error e number n
   set e to e & return & return & "Num: " & n
   tell me to set dDlg to display dialog e with title "ERROR!" buttons {"Cancel", "Copy", "OK"} default button "OK"
   if button returned of dDlg = "Copy" then set the clipboard to e
end try

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

(*

Change List

2018/11/07 02:15
   + New files creation and modification dates are changed to NOW() when the user creates them.
      (Before this all dates except .txt files were the same as the template file.)

2018/11/15 02:27
   - Removed old, redundant Text_Template.txt creation code.
   + Previously an error was thrown if the user cancelled – this is no longer the case.
   + Fixed a bug that stopped duplicated files from changing creation and modification dates to NOW().

*)

----------------------------------------------------------------
1 Like

Hey Folks,

I've made some minor changes and bug-fixes to the script in post #8 above.

Thanks to @Tom for his feedback on the script.

-Chris

Hey Folks,

Here's a somewhat more modern version of above script that I've turned into a macro.

The macro pops-up a pick-list of available templates.

image

When a template is selected the user is given the opportunity to rename it.

21

All templates MUST have file-extensions.

The macro will preserve the file-extension, so the user doesn't need to worry about it when renaming the file.

All date properties of the newly created file are reset to NOW(), so finding by creation-date or modification-date is more accurate.

The new file is installed in the frontmost Finder window.

Enjoy.

-Chris


New File Here- (from a Template) v2.00.kmmacros (17 KB)

Macro Image

3 Likes

Dear Chris,
Thank you for your gracious answer.
Your new macro worked fine.
May I ask a question?
How do I change the storage location of a newly created file?
Where should I put in the PATH I would like to change?
Best regards, WAKAMATSU (boehmflute)

Hey @boehmflute,

You don't -- the new file is installed in the frontmost Finder window (or the Desktop if no window is open).

In general when I use a template I want it now. In fact I need to make an option to immediately open the new file in its default application...

Are you wanting an alternate location?

If so then give me an example path, and I'll think on the best way to accomplish it.

-Chris

All the credit goes to Chris @ccstone for a great macro/script.

Actually, this is very doable with a small change to the AppleScript:

  tell application "Finder"
    ### REPLACE Block to Get destFolder from User Prompt ###JMTX CHG
    try
      set finderInsertionLocation to (insertion location as alias)
      set destFolder to POSIX path of (choose folder with prompt ¬
        "Choose Folder for NEW FILE" default location finderInsertionLocation)
    on error
      set destFolder to POSIX path of (choose folder with prompt ¬
        "Choose Folder for NEW FILE")
    end try
    
  end tell

It uses the Finder Insertion Location as the default folder (if it exists), but then prompts the user to pick the folder for the new file.

Here's the entire script with my mods. Just replace the last AppleScript in @ccstones macro with the below script.

AppleScript to Prompt User for New File Folder

-------------------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2019/02/02 16:54
# dMod: 2019-02-03  16:40  by JMichaelTX
# Appl: Finder, Keyboard Maestro Engine
# Task: Creating a new file from a template file in the Finder's Insertion Location.
# Mod by JMichaelTX:  Prompt User for Folder for New File
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @Finder, @Keyboard_Maestro_Engine, @Create, @New, @File, @Template, @Insertion, @Location
-------------------------------------------------------------------
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
-------------------------------------------------------------------

try
  
  # Get variables from Keyboard Maestro
  tell application "Keyboard Maestro Engine"
    set chosenFilePath to getvariable "chosenTemplate"
    set newFileName to getvariable "newFileName"
    set fileExt to getvariable "fileExt"
  end tell
  
  tell application "Finder"
    ### REPLACE Block to Get destFolder from User Prompt ###JMTX CHG
    try
      set finderInsertionLocation to (insertion location as alias)
      set destFolder to POSIX path of (choose folder with prompt ¬
        "Choose Folder for NEW FILE" default location finderInsertionLocation)
    on error
      set destFolder to POSIX path of (choose folder with prompt ¬
        "Choose Folder for NEW FILE")
    end try
    
  end tell
  
  ----------------------------------------------------------------
  
  # Setup for AppleScriptObjC.
  set sourcePath to current application's NSString's stringWithString:chosenFilePath
  set sourceName to sourcePath's lastPathComponent()'s stringByDeletingPathExtension()
  set sourceExt to sourcePath's pathExtension()
  
  ###  set destFolder to finderInsertionLocation  ##JMTX Delete
  
  set destFolder to current application's NSString's stringWithString:destFolder
  set someName to current application's NSUUID's UUID()'s UUIDString() -- unique UUID string
  set destTempPath to destFolder's stringByAppendingPathComponent:someName
  
  # Move or copy to temp path:
  set fileManager to current application's NSFileManager's defaultManager()
  fileManager's copyItemAtPath:sourcePath toPath:destTempPath |error|:(missing value)
  
  set newFilePath to (destFolder's stringByAppendingPathComponent:(newFileName & "." & fileExt))
  
  --» Try to rename the newly copied file:
  set renameResult to fileManager's moveItemAtPath:destTempPath toPath:newFilePath |error|:(missing value)
  
  --» Try renaming with a serial number if the above rename action fails.
  if renameResult as boolean is false then
    repeat with i from 1 to 1000
      set destName to current application's NSString's stringWithFormat_("%@-%@.%@", sourceName, i, sourceExt)
      set renameResult to (fileManager's moveItemAtPath:destTempPath toPath:(destFolder's stringByAppendingPathComponent:destName) |error|:(missing value))
      set newFilePath to (destFolder's stringByAppendingPathComponent:destName)
      if renameResult as boolean then exit repeat
    end repeat
  end if
  
  if renameResult as boolean is false then
    error "Failure in while renaming template file!"
  end if
  
  set theDate to current date
  
  set theURL to (current application's |NSURL|'s fileURLWithPath:(newFilePath as text))
  
  set {resultOfCreationDate, theError} to (theURL's setResourceValue:theDate forKey:(current application's NSURLCreationDateKey) |error|:(reference))
  if resultOfCreationDate as boolean is false then error (theError's localizedDescription() as text)
  
  set {resultOfModificationDate, theError} to (theURL's setResourceValue:theDate forKey:(current application's NSURLContentModificationDateKey) |error|:(reference))
  if resultOfModificationDate as boolean is false then error (theError's localizedDescription() as text)
  
  set {resultOfContentAccessDate, theError} to (theURL's setResourceValue:theDate forKey:(current application's NSURLContentAccessDateKey) |error|:(reference))
  if resultOfContentAccessDate as boolean is false then error (theError's localizedDescription() as text)
  
  set newFileAlias to alias POSIX file (newFilePath as text)
  
  --» Reveal the new file in the front Finder window.  
  tell application "Finder"
    set fileParent to parent of newFileAlias
    tell fileParent to update
    delay 0.15
    reveal newFileAlias
    delay 0.15
    tell fileParent to update
  end tell
  
on error e number n
  set e to e & return & return & "Num: " & n
  if n ≠ -128 then
    try
      tell application (path to frontmost application as text) to ¬
        set ddButton to button returned of ¬
          (display dialog e with title ¬
            "ERROR!" buttons {"Copy Error Message", "Cancel", "OK"} ¬
            default button "OK" giving up after 30)
      if ddButton = "Copy Error Message" then set the clipboard to e
    end try
  end if
end try

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

Dear Chris,
It seems that I was misunderstanding the concept of template.
An environment is created that uses the file I normally use as "template".
I should have understood this way, right?
I will try to find the right way.
If I get lost, will I ask again? Do not you get annoyed?
Best regards, WAKAMATSU (boehmflute)

Hey @boehmflute,

Well, it's clear that we're not communicating clearly...  :sunglasses:

-Chris

A post was split to a new topic: Experiments in LaTex

Well...

Indeed...

I am COMPLETLEY new to Mac, I've ran WinX and Linux for years, I start a new job 3 weeks ago 2 days after the CEO made a sweeping change and decided all new players new macs...

I'll be honest, I was a little disappointed and teaching a (somewhat) old[er] dog some new tricks.

I have written 1001 scripts for windows and I was very very nervous when learning I had to write something in AS to get a right click context menu working...

But in its own way, Im actually getting used to it and feel like I am turning to the darkside!

TBH I just wanted to thank every Dev on here who has contributed to this script. I am also pleased to find a forum where I can ask a question and the answer isnt marked as 'Why do you have a mac?' (I'm looking at you Stackoverflow...)

Thank you all.

3 Likes

AS is difficult, but it does hook to many apps. Look at Ruby or Python for general scripting. And of course KM for communicating with apps.

Also you can run shell scripts. Current shell is zsh. macOS is built on some version of UNIX, so as I assume means most Linux stuff transfers over.

Hi Chris,

Great work on this script and thank you so much for sharing. I know this is a relatively older script you wrote, but it still works perfect.

Although everytime I run it, it prompts me to allow it with either touchID, Apple Watch, or password. Is there any way to disable this?

Thank you!