How to exclude locked files or folders In an AppleScript that selects all files in a particular folder

applescriptfinder

Here's my situation. I created an AppleScript for cleaning up my desktop. It essentially selects all files and folders on my desktop, creates a new folder with a specific name and date format, and moves all the files from my desktop to the new folder. This script works beautifully until I realized that occasionally there were files or folders I wanted to remain on my desktop. My solution was to open the get info window for each file or folder that I wanted to remain on my desktop, and select the “lock” option in the get info window.

My problem is now because of the locked files, the script cannot completely execute without displaying an error message. If I click “OK” on the error message, the script will finish and move every file with the exception of the ones that are locked.

I would prefer not to have to go through this extra step by clicking the okay button. I tried adding some system event actions to the script to automatically click the “ok” button and that did not work.

I'm starting to think that the only real solution would be to not select those locked files or folders in the first place. This is where I am lost. Can anyone help direct me as to how to avoid selecting the locked files in the first place?

enter image description here


Here is the script in its entirety.


set scriptPath to (load script file "Macintosh HD:Users:Smokestack:Library:Mobile Documents:com~apple~ScriptEditor2:Documents:Cleanup Desktop.scptd:Contents:Resources:Scripts:Current Time A.M. P.M. And Short Date.scpt")

tell scriptPath
    timeandDate() -- This will get the time and date in this format "05/31/2017 @ 9:10:48 PM" called from the loaded script file above
end tell

set timeandDate to the result -- This will copy the time and date results from the previous step and and set it as this new variable

tell application "Finder"
    if running then
        close every window
        activate
        make new Finder window
        set target of Finder window 1 to folder "Desktop" of folder "Smokestack" of folder "Users" of startup disk
    end if
    open Finder window 1
    activate
end tell

delay 1
tell application "System Events"
    key code 0 using (command down) -- This will select all files and folders on the desktop in the active finder window
end tell

tell application "Finder"
    set these_items to the selection
    set destinationFolder to make new folder at POSIX file "/Users/Smokestack/Jimz_Important_Stuff/Desktop_Cleanups/" with properties {name:timeandDate}
    move these_items to destinationFolder
    reveal destinationFolder
end tell

Here is a revised version of the script without calling handlers from external files

on timeandDate()
    set CurrentTime to (time string of (current date))
    set AppleScript's text item delimiters to ","
    set theLongDate to (current date)
    set theLongDate to (date string of theLongDate)
    set currentMonth to (word 1 of text item 2 of theLongDate)
    set currentDay to (word 2 of text item 2 of theLongDate)
    set currentYear to (word 1 of text item 3 of theLongDate)
    set monthList to {January, February, March, April, May, June, July, August, September, October, November, December}
    repeat with x from 1 to 12
        if currentMonth = ((item x of monthList) as string) then
            set theRequestNumber to (text -2 thru -1 of ("0" & x))
            exit repeat
        end if
    end repeat
    set currentMonth to theRequestNumber
    set currentDay to (text -2 thru -1 of ("0" & currentDay))
    set theShortDate to (currentMonth & "/" & currentDay & "/" & currentYear) as string
    set CurrentTime to (time string of (current date))
    set CurrentTimeandShortDate to (theShortDate & " @ " & CurrentTime)
    set AppleScript's text item delimiters to ""
end timeandDate

timeandDate()

set timeandDate to the result

tell application "Finder"
    close every window
    activate
    make new Finder window
    set target of Finder window 1 to folder "Desktop" of folder "Smokestack" of folder "Users" of startup disk
    select every file of the front Finder window 
    delay 1
    set these_items to the selection
    set destinationFolder to make new folder at POSIX file "/Users/Smokestack/Jimz_Important_Stuff/Desktop_Cleanups/" with properties {name:timeandDate}
    try
        move these_items to destinationFolder
    end try
    reveal destinationFolder
end tell

After making some revisions to the script, as long as the locked items on my desktop are only folders and not files, now this script works beautifully. However it will still generate an error if there are any individual locked files.

Best Answer

Update: As I mentioned somewhere in the comments that I'd build out a 10.12.5 system this past weekend and do some testing, I did.

Here is what I found out:

  • The code of my answer, inclusive of edit 5 on Jun 2 at 15:34, works on my system without issue.
  • After a review of all code and comments, it dawned on me that while my code, as is, worked on my system and I gave note referencing the delay command having to adjust values and or add/remove as/if necessary, etc., that this mainly comes down to timing issues and the pitfalls of that particular form of event coding.

Therefore, and while I'll leave the original answer at the bottom of this update, I decided to look at this from a different programatic angle and offer the following code as a better way to code this script to accomplish the task at hand.

This new code, does not rely on closing opened Finder windows and then opening a Finder window to the Desktop folder of the User to then have System Events select all items in the target folder, or the use of the delay command to deal with timing issues etc. All of which I personally don't like, because I don't want all Finder windows I have opened, closed to accomplish a task such as this. Or code it to leave the existing windows opened while ensuring the Finder window of the Desktop folder within the Home folder is the topmost Finder window to ensure System Events selects the correct items and get the timings right, etc.!

The following AppleScript code offers a more safe and faster way to accomplish the task at hand and I encourage you to use it over the previous code examples.

Note: With the previous caveats in play, (the existence of the folder the destination folder is created in, etc.), you should not not need to modify this code and should be able to use it as is. That is to say, you're certainly free to modify the code anyway you need/want, but as is, it should work.

New AppleScript code:

tell current application
    try
        tell application "Finder"
            if running then
                set theseFileSystemObjects to (get every item of (path to desktop))
                set theFileSystemObjectsNotLocked to {}
                repeat with i from 1 to (count of theseFileSystemObjects)
                    set thisFileSystemObject to (item i of theseFileSystemObjects)
                    if not locked of (get properties of thisFileSystemObject) then
                        set end of theFileSystemObjectsNotLocked to thisFileSystemObject
                    end if
                end repeat
                if theFileSystemObjectsNotLocked is not equal to {} then
                    tell current application to set theDateTimeNow to ¬
                        (do shell script "date '+%m.%d.%Y @ %I.%M.%S %p'") as string
                    set theDestinationFolder to make new folder at ¬
                        ((path to home folder as string) & "Jimz_Important_Stuff:Desktop_Cleanups:") with properties {name:theDateTimeNow}
                    move theFileSystemObjectsNotLocked to theDestinationFolder
                    open theDestinationFolder
                    activate theDestinationFolder
                end if
            else
                tell current application
                    activate
                    display dialog "Finder is not currently running!" & linefeed & linefeed & ¬
                        "Open Finder, then run Desktop Clean Up again." buttons {"OK"} ¬
                        default button 1 with title "Desktop Clean Up"
                end tell
            end if
        end tell
    on error eStr number eNum
        activate
        display dialog eStr & " number " & eNum buttons {"OK"} ¬
            default button 1 with title "Desktop Clean Up" with icon caution
        return
    end try
end tell

Original Answer:

This is an example of how I'd write the entire script to be run, as is, as either a .scpt file or an .app file, on your system. I'm saying your system, because the target destination folder is set for your system.

There is no need to load an outside resource and no handler to set the value of the variable used for the destination folder name. I choose to use a do shell script command for that, using the date command to return a custom date time string variable, as it's one line of code compared to the amount of code in the on timeandDate() handler, and it returns the same pattern.

I will continue to use this on my system with appropriately adjusted pathnames and a different pattern for the destination folders name, replacing the / and : with . in the custom date time string variable used in the destination folder name.

As coded, this first version of the script moves all file system objects, that are not locked, currently in the Desktop folder to the destination folder. The script includes minimal appropriate error handling and as coded you shouldn't have the issues you were previously having. This of course assumes that the $HOME/Jimz_Important_Stuff/Desktop_Cleanups folder exists. If not, you'll get the appropriate error message, however additional error handling could be added to create the hierarchical folded structure as/if necessary.

This first script should resolve all issues you are/were having with your own code and IMO is a better way to code it then just trapping and eating the error with just a try statement alone, because as coded, it can only move files that are not locked and doesn't even try to move a locked file.

This was tested under macOS 10.12.3 and should work for you on macOS 10.12.5, which you're presently running.

AppleScript Code:


tell current application
    try
        set theDateTimeNow to (do shell script "date '+%m/%d/%Y @ %I:%M:%S %p'") as string
        tell application "Finder"
            if running then
                close every window
                set target of (make new Finder window) to (path to desktop)
                activate
                delay 0.5
                tell application "System Events" to key code 0 using {command down}
                delay 0.5
                set theseFileSystemObjects to the selection
                set theDestinationFolder to make new folder at ¬
                    ((path to home folder as string) & "Jimz_Important_Stuff:Desktop_Cleanups:") with properties {name:theDateTimeNow}
                set theListOfFileSystemObjectsNotLocked to {}
                repeat with i from 1 to (count of theseFileSystemObjects)
                    set thisFileSystemObject to (item i of theseFileSystemObjects)
                    if not locked of thisFileSystemObject then
                        set end of theListOfFileSystemObjectsNotLocked to thisFileSystemObject
                    end if
                end repeat
                move theListOfFileSystemObjectsNotLocked to theDestinationFolder
                reveal theDestinationFolder
            else
                tell current application
                    activate
                    display dialog "Finder is not currently running!" & linefeed & linefeed & ¬
                        "Open Finder, then run Desktop Clean Up again." buttons {"OK"} ¬
                        default button 1 with title "Desktop Clean Up" with icon caution
                end tell
            end if
        end tell
    on error eStr number eNum
        activate
        display dialog eStr & " number " & eNum buttons {"OK"} ¬
            default button 1 with title "Desktop Clean Up" with icon caution
        return
    end try
end tell

Note: As to the value of the delay commands, they may need to be adjusted for your system and or additional ones added as/if necessary and or removed if not needed. As presently coded, this script worked without issue, dozens of times in testing on my system, with varying counts and sizes of file system objects being acted upon in the Desktop folder. Make any adjustments as necessary.

The file system objects tested were, files, folders, aliases, symlinks, application bundles and document bundles, the latter two of which are just folders. These FSOs were of various sizes, both locked and not locked.


This second version of the script goes beyond your expressed needs and makes a duplicate of the locked file system objects currently in the Desktop folder to the destination folder, while reseting the locked flag on the duplicates so they can be deleted without raising a flag at the time you may choose to delete them. I'm including it as it may have added value and you find it useful.

AppleScript Code:


tell current application
    try
        set theDateTimeNow to (do shell script "date '+%m/%d/%Y @ %I:%M:%S %p'") as string
        tell application "Finder"
            if running then
                close every window
                set target of (make new Finder window) to (path to desktop)
                activate
                delay 0.5
                tell application "System Events" to key code 0 using {command down}
                delay 0.5
                set theseFileSystemObjects to the selection
                set theDestinationFolder to make new folder at ¬
                    ((path to home folder as string) & "Jimz_Important_Stuff:Desktop_Cleanups:") with properties {name:theDateTimeNow}
                set theListOfFileSystemObjectsNotLocked to {}
                set theListOfLockedFileSystemObjects to {}
                repeat with i from 1 to (count of theseFileSystemObjects)
                    set thisFileSystemObject to (item i of theseFileSystemObjects)
                    if not locked of thisFileSystemObject then
                        set end of theListOfFileSystemObjectsNotLocked to thisFileSystemObject
                    else
                        set end of theListOfLockedFileSystemObjects to thisFileSystemObject
                    end if
                end repeat
                move theListOfFileSystemObjectsNotLocked to theDestinationFolder
                duplicate theListOfLockedFileSystemObjects to theDestinationFolder
                repeat with i from 1 to (count of theListOfLockedFileSystemObjects)
                    set thisFileSystemObject to (item i of theListOfLockedFileSystemObjects)
                    set locked of alias ((theDestinationFolder as string) & name of thisFileSystemObject) to false
                end repeat
                reveal theDestinationFolder
            else
                tell current application
                    activate
                    display dialog "Finder is not currently running!" & linefeed & linefeed & ¬
                        "Open Finder, then run Desktop Clean Up again." buttons {"OK"} ¬
                        default button 1 with title "Desktop Clean Up" with icon caution
                end tell
            end if
        end tell
    on error eStr number eNum
        activate
        display dialog eStr & " number " & eNum buttons {"OK"} ¬
            default button 1 with title "Desktop Clean Up" with icon caution
        return
    end try
end tell