Sunday, August 20, 2017

#1 2016-12-21 06:50:42 am

drp638
Member
Registered: 2009-01-02
Posts: 11

Convert script to folder action

Hi Folks,
  I have a script here that works just fine, but I'd like it to be a folder action that I can attach to a folder so that filenames are changed as they are added to the folder (volume). I do not know how to do this though, can someone provide direction? -thanks, dan

here is script, it simply removes underscores:

set defDel to AppleScript's text item delimiters
tell application "Finder"
    set theFolder to folder (choose folder)
    repeat with thisItem in theFolder
        set thename to name of thisItem
        if thename contains "_" then
            set AppleScript's text item delimiters to "_"
            set newName to text items of thename
            set AppleScript's text item delimiters to ""
            set name of thisItem to (newName as string)
            set AppleScript's text item delimiters to defDel
        end if
    end repeat
end tell

Offline

 

#2 2016-12-21 10:04:27 am

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 3182

Re: Convert script to folder action

You may try:

Applescript:

on adding folder items to this_folder after receiving added_items
   set defDel to AppleScript's text item delimiters
   tell application "System Events"
       if type identifier of (item 1 of added_items) is "public.folder" then
           set added_items to added_items & disk items of (item 1 of added_items)
       end if
       repeat with thisItem in added_items
           try
               if visible of thisItem then
                   set thename to name of thisItem --disk item thisItem
                   if thename contains "_" then
                       set AppleScript's text item delimiters to "_"
                       set newName to text items of thename
                       set AppleScript's text item delimiters to ""
                       set name of thisItem to (newName as string)
                   end if
               end if
           end try
       end repeat
   end tell
   set AppleScript's text item delimiters to defDel
end adding folder items to

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) mercredi 21 décembre 2016 16:04:22

Last edited by Yvan Koenig (2016-12-22 06:08:26 am)

Offline

 

#3 2016-12-21 10:53:05 am

drp638
Member
Registered: 2009-01-02
Posts: 11

Re: Convert script to folder action

Yvan,
    Thank you for your reply, this is working fine and I have learned something.
Merci, Dan

Offline

 

#4 2016-12-21 11:09:52 am

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 3182

Re: Convert script to folder action

Thanks for the feedback.
I'm not fully satisfied by the posted code.
I'm quite sure that there is a way to clean it a bit but at this time  I'm switching between four tasks:rolleyes:

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) mercredi 21 décembre 2016 17:09:47

Offline

 

#5 2016-12-23 07:01:19 am

drp638
Member
Registered: 2009-01-02
Posts: 11

Re: Convert script to folder action

One thing I am not accomplishing here is that when a renamed file matches that of an existing file, the old file is not replaced by the new but that is what I'd like to have happen. Any ideas on how this can be integrated into this script?
-dan

AppleScript: 2.4.3
Browser: Safari 537.36
Operating System: Mac OS X (10.7)

Offline

 

#6 2016-12-23 08:55:40 am

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 3182

Re: Convert script to folder action

It's a bit boring to be given elements of the question one after the other. Is it so difficult to think a bit before asking so that the question describe precisely and completely what is needed. As far as I know, macScripter is not a forum of soothsayers.

Your original question was only about renaming the files embedded in the selected folder.
Must I understand that this folder may contain files whose modified name would be identical to already existing files ?
example : the dropped folder is named share and contain the files :
…share:ab_cd_ef
…share:abcdef

Must I understand too that if you drop a folder whose name contain underscores, it must replace an other folder whose name matches the new one deprived of underscores ?
example: the folder to which the script is attached contains a folder named share1 and the dropped folder is named share_1
This was not part of the original question.

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) vendredi 23 décembre 2016 14:55:36

Offline

 

#7 2016-12-23 09:32:46 am

drp638
Member
Registered: 2009-01-02
Posts: 11

Re: Convert script to folder action

Yvan, I appreciate the wry, peeved humor and don't mean to drag you around. I am in the dark enough that I didn't even realize I'd need to account for this.

It is true, that a newly renamed file must replace another file whose name matches the new one deprived of underscores and this is the ultimate goal. The items that would land at the destination would be files only, not folders and the destination is a folder on a server that is shared out as a volume. The script runs on the server's system. Hopefully there are no other unseen surprises.

best, dan

Offline

 

#8 2016-12-23 11:59:17 am

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 3182

Re: Convert script to folder action

You asked for a folder action.
This tool is triggered when we drop items onto the folder to which it is attached.
To achieve what you describe, we don't have to drag and drop a folder onto the folder to which the script is attached, we must drag and drop the group of files.
An alternative would be to drag and drop a folder so that the script would rename the items embedded in the dropped folder then execute a move with replacing action for every file. then, at last it would delete the folder.
To achieve this task, it would be useful to know if the items may be folders or packages.

Worse, as I never use servers, I don't know if a script may be attached to a folder stored on a network.

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) vendredi 23 décembre 2016 17:59:12

Offline

 

#9 2016-12-23 12:23:20 pm

drp638
Member
Registered: 2009-01-02
Posts: 11

Re: Convert script to folder action

The server is a macOS server and a folder on that server that is shared receives files (only) across the network from another server. I am operating the script from there so to the system, it is a local directory. The destination folder may receive the same file multiple times as it is revised. On the destination, we only want one copy of it, the newest. If I could control the file naming coming from the other system, I would not need this at all. The removal of the underscore is the goal. I did not anticipate the overwrite issue.
-dan

Offline

 

#10 2016-12-23 01:48:34 pm

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 3182

Re: Convert script to folder action

For me the fact that the server is a macOS Server makes no difference, I've no experience with them.

The script below was tested with a folder stored on a local device.
You may drop a folder or a group of files on the folder to which it is attached.

Applescript:

on adding folder items to this_folder after receiving added_items
   # underscore in varName of class file, folder or alias
   local maybe_Folder, added_items, this_Item
   # no underscore in varName of class boolean , text or list of text items
   local thisFolder, qpFolder, defDel, droppedAfolder, droppedFolder, listToMove, thisItem, thename, nameAsList
   set thisFolder to this_folder as text
   set qpFolder to quoted form of (POSIX path of this_folder)
   set defDel to AppleScript's text item delimiters
   set droppedAfolder to false
   set maybe_Folder to contents of (item 1 of added_items)
   
   tell application "System Events"
       if type identifier of maybe_Folder is "public.folder" then
           set droppedAfolder to true
           set added_items to disk items of maybeFolder
           set droppedFolder to maybe_Folder as text
       end if
       if droppedAfolder then
           set listToMove to {}
           repeat with this_Item in added_items
               try
                   set thisItem to path of this_Item
                   set thename to name of this_Item
                   if visible of this_Item then
                       if thename contains "_" then
                           set AppleScript's text item delimiters to "_"
                           set nameAsList to text items of thename
                           set AppleScript's text item delimiters to ""
                           set thename to nameAsList as string
                           set name of this_Item to thename
                           set thisItem to droppedFolder & thename
                       end if # thename contains "_"
                       if exists disk item thename of this_folder then delete disk item (thisFolder & thename)
                       set end of listToMove to my getQuotedPosixPath(thisItem)
                   end if
               end try
           end repeat
           if listToMove ≠ {} then
               set listToMove to my recolle(listToMove, space)
               tell me to do shell script "mv " & listToMove & space & qpFolder
           end if
           delete maybe_Folder
       else
           # The first item of the list of dropped items is not a folder
           repeat with this_Item in added_items
               try
                   set thisItem to path of this_Item
                   set thename to name of this_Item
                   if visible of this_Item then
                       if thename contains "_" then
                           set AppleScript's text item delimiters to "_"
                           set nameAsList to text items of thename
                           set AppleScript's text item delimiters to ""
                           set thename to nameAsList as string
                           if exists disk item thename of this_folder then
                               delete disk item (thisFolder & thename)
                               delay 0.2
                           end if
                           set name of this_Item to thename
                       end if # thename contains "_"
                   end if # visible of thisItem
               end try
           end repeat
       end if # droppedAfolder
   end tell # System Events
   set AppleScript's text item delimiters to defDel
   
end adding folder items to

#=====

on getQuotedPosixPath(anItem)
   return quoted form of POSIX path of anItem
end getQuotedPosixPath

#=====

on recolle(l, d)
   local oTIDs, t
   set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d}
   set t to l as text
   set AppleScript's text item delimiters to oTIDs
   return t
end recolle

#=====

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) vendredi 23 décembre 2016 19:48:13

Offline

 

#11 2016-12-23 02:36:40 pm

drp638
Member
Registered: 2009-01-02
Posts: 11

Re: Convert script to folder action

wow. wouah.
I look forward to trying this out. Thanks very much for sharing your depth of knowledge. Will post on return to work next week.
-dan

Offline

 

#12 2016-12-25 02:50:34 pm

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 3182

Re: Convert script to folder action

Here is a version using several ASObjC functions.
Maybe I will rework it to drop completely System Events.

Applescript:

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

on adding folder items to this_folder after receiving added_items
   # underscore in varName of class file, folder or alias
   local maybe_Folder, added_items, this_Item
   # no underscore in varName of class boolean , text or list of text items
   local thisFolder, qpFolder, defDel, droppedAfolder, droppedFolder, listToMove, thisItem, thename, nameAsList
   (*
set this_folder to ((path to desktop as text) & "Share:") as alias
set added_items to {((path to desktop as text) & "Share:some items copie:") as alias}
*)

   set thisFolder to this_folder as text
   set droppedAfolder to false
   set maybe_Folder to contents of (item 1 of added_items)
   
   tell application "System Events"
       if type identifier of maybe_Folder is "public.folder" then
           set droppedAfolder to true
           set added_items to disk items of maybe_Folder whose visible is true
           set droppedFolder to maybe_Folder as text
       end if
       if droppedAfolder then
           set listToMove to {}
           repeat with this_Item in added_items
               try
                   set thisItem to path of this_Item
                   set thename to name of this_Item
                   if visible of this_Item then
                       if thename contains "_" then
                           set thename to (my replace:thename existingString:"_" newString:"")
                           set name of this_Item to thename
                           set thisItem to droppedFolder & thename
                       end if # thename contains "_"
                       (my moveThis:(thisItem) toThisItem:(thisFolder & thename))
                   end if
               end try
           end repeat
           delete folder droppedFolder
       else
           # The first item of the list of dropped items is not a folder
           repeat with this_Item in added_items
               try
                   set thisItem to path of this_Item
                   set thename to name of this_Item
                   if visible of this_Item then
                       if thename contains "_" then
                           set thename to (my replace:thename existingString:"_" newString:"")
                           (my deleteIfExists:(thisFolder & thename))
                           set name of this_Item to thename
                       end if # thename contains "_"
                   end if # visible of thisItem
               end try
           end repeat
       end if # droppedAfolder
   end tell # System Events
   
end adding folder items to

#=====

on replace:sourceString existingString:d1 newString:d2
   set sourceString to current application's NSString's stringWithString:sourceString
   return (sourceString's stringByReplacingOccurrencesOfString:d1 withString:d2) as text
end replace:existingString:newString:

#=====

on deleteIfExists:HFSpath
   set POSIXPath to POSIX path of HFSpath
   set FileManager to current application's NSFileManager's defaultManager --> <NSFileManager: 0x7f8581603da0>
   set FileExists to FileManager's fileExistsAtPath:POSIXPath
   if FileExists then set WasSucessful to FileManager's removeItemAtPath:POSIXPath |error|:(missing value)
end deleteIfExists:

#=====

on moveThis:HFSpath toThisItem:HFSNewItem
   set POSIXPath to POSIX path of HFSpath
   set POSIXNewItem to POSIX path of HFSNewItem
   set FileManager to current application's NSFileManager's defaultManager --> <NSFileManager: 0x7f8581603da0>
   set FileExists to FileManager's fileExistsAtPath:POSIXNewItem
   if FileExists then set WasSucessful to FileManager's removeItemAtPath:POSIXNewItem |error|:(missing value)
   set WasSucessful to FileManager's moveItemAtPath:POSIXPath toPath:POSIXNewItem |error|:(missing value)
   if (not WasSucessful) then
       display dialog "Could not move the file “" & POSIXPath & "”." buttons {"Cancel", "OK"} default button "OK"
       return false
   end if
end moveThis:toThisItem:

#====

CAUTION: As both versions use POSIX and HFS path they would fail if the HFS filenames contain slashes.

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) dimanche 25 décembre 2016 20:50:24

Offline

 

#13 2016-12-26 12:44:25 pm

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 3182

Re: Convert script to folder action

I hope that you all had a Merry Christmas.

Here is a version using neither Finder nor System Events.

Applescript:

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

on adding folder items to this_folder after receiving added_items
   # underscore in varName of class file, folder or alias
   local added_items, this_Item
   # no underscore in varName of class boolean , text or list of text items
   local POSIXFolder, droppedPOSIXFolder, FileManager, FileAttributes, droppedAfolder, added_names, aName
   local NSPOSIXItem, NSNewPOSIXPath, NSPOSIXOrig, NSPOSIXMoved, theResult, theError
   (*
   # Used during tests to mimic passed datas.
   set thisFolder to ((path to desktop as text) & "parent:")
   set this_folder to thisFolder as alias
   set added_items to {(thisFolder & "DSC_0049.jpg") as alias, (thisFolder & "Position_01:") as alias}
   -- set added_items to {(thisFolder & "parent copie:") as alias}
   *)

   # As passed datas are Hfs aliases, every folder path ends with a colon
   set POSIXFolder to POSIX path of this_folder # with an ending slash
   set droppedPOSIXFolder to POSIX path of (item 1 of added_items) # with an ending slash
   
   set FileManager to current application's NSFileManager's defaultManager
   set FileAttributes to FileManager's attributesOfItemAtPath:droppedPOSIXFolder |error|:(missing value)
   set droppedAfolder to (FileAttributes's objectForKey:(current application's NSFileType)) as text is "NSFileTypeDirectory"
   
   if droppedAfolder then
       # Build a list of "posix" names: if the Hfs name contains a slash, in the "posix" name it's replaced by a colon
       set added_names to (FileManager's contentsOfDirectoryAtPath:droppedPOSIXFolder |error|:(missing value)) as list
       repeat with aName in added_names
           if aName does not start with "." then
               try
                   set NSPOSIXItem to (current application's NSString's stringWithString:(droppedPOSIXFolder & aName))
                   if aName contains "_" then
                       # Builds the new name
                       set aName to (my replace:aName existingString:"_" newString:"")
                       set NSNewPOSIXPath to (current application's NSString's stringWithString:(droppedPOSIXFolder & aName))
                       # Rename the file. Here both paths MUST be NSStrings
                       set {theResult, theError} to (FileManager's moveItemAtPath:NSPOSIXItem toPath:NSNewPOSIXPath |error|:(reference))
                       copy NSNewPOSIXPath to NSPOSIXOrig
                   else
                       copy NSPOSIXItem to NSPOSIXOrig
                   end if # thename contains "_"
                   # Builds the path to the moved item
                   set NSPOSIXMoved to (current application's NSString's stringWithString:(POSIXFolder & aName))
                   # If there is already an item with the given name, delete it.
                   # The given path may be a POSIX path or an NSString built upon a POSIX path (what it's here)
                   if (FileManager's fileExistsAtPath:NSPOSIXMoved) then
                       set theResult to (FileManager's removeItemAtPath:NSPOSIXMoved |error|:(missing value))
                   end if
                   # Move the item. Here both paths MUST be NSStrings
                   set {theResult, theError} to (FileManager's moveItemAtPath:NSPOSIXOrig toPath:NSPOSIXMoved |error|:(reference))
               end try
           end if
       end repeat
       # Delete the dropped folder. The give path may be a POSIX path (what it's here) or an NSString built upon a POSIX path
       set theResult to FileManager's removeItemAtPath:droppedPOSIXFolder |error|:(missing value)
   else
       # The first item of the list of dropped items is not a folder
       repeat with this_Item in added_items
           try
               set NSPOSIXItem to (current application's NSString's stringWithString:(POSIX path of this_Item))
               set aName to NSPOSIXItem's lastPathComponent() as text
               if aName does not start with "." then
                   if aName contains "_" then
                       set aName to (my replace:aName existingString:"_" newString:"")
                       set NSNewPOSIXPath to (current application's NSString's stringWithString:(POSIXFolder & aName))
                       # If there is already an item with the new name, delete it
                       if (FileManager's fileExistsAtPath:NSNewPOSIXPath) then
                           set theResult to (FileManager's removeItemAtPath:NSNewPOSIXPath |error|:(missing value))
                       end if
                       # Rename the file
                       set {theResult, theError} to (FileManager's moveItemAtPath:NSPOSIXItem toPath:NSNewPOSIXPath |error|:(reference))
                   end if # aName contains "_"
               end if # visible of POSIXItem
           end try
       end repeat
   end if # droppedAfolder
   
end adding folder items to

#=====

on replace:sourceString existingString:d1 newString:d2
   set sourceString to current application's NSString's stringWithString:sourceString
   return (sourceString's stringByReplacingOccurrencesOfString:d1 withString:d2) as text
end replace:existingString:newString:

#=====

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) lundi 26 décembre 2016 18:43:34

Offline

 

#14 2016-12-28 06:31:19 am

drp638
Member
Registered: 2009-01-02
Posts: 11

Re: Convert script to folder action

Thank you Yvan,
   Yes, an enjoyable Christmas - likewise.

Thanks for your extensive work on this - it is actually beyond my understanding but I now have a script that is doing exactly what I need it to: changing the names of files that I can't control at their creation and replacing the files with the undesired names.
Best, Dan

Offline

 

#15 2016-12-28 09:10:07 am

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 3182

Re: Convert script to folder action

Thanks for the feedback.
Which version are you using?
Knowing it I will comment it to help you to understand what it does.

Yvan KOENIG running Sierra 10.12.2 in French (VALLAURIS, France) mercredi 28 décembre 2016 15:09:41

Offline

 

#16 2016-12-30 02:56:05 pm

drp638
Member
Registered: 2009-01-02
Posts: 11

Re: Convert script to folder action

I am using the version from 2016-12-23 01:48:34 pm. Have not had a chance to test/try the "Foundation" versions yet. Will let you know if I do. Happy New Year, Dan

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)