Search code examples
downloadcopyapplescriptunzip

AppleScript - Copying Folder Content shows error - Download & UnZip Works


UPDATE01: The cleaned Up code - Zip download was removed and current issue is that the 'Copy' command gets executed before 'unzip' is completed; resulting in a copy of an empty folder over to the destination folder. when running as an .app but when running as a script in AppleScriptEditor.. it runs fine :/

property DownloadsFolder : path to downloads folder
property appSupport : path to application support from user domain
property ZIPName : "ResourcesOffline.zip" -- downloaded ZIP file
property AppName : "MyApp" -- name of App in Application Support
property ExtractedFolderName : "MyContent" -- name for folder in Downloads where ZIP is saved
property ExtractedFolderPath : ((DownloadsFolder as text) & ExtractedFolderName & ":")
property DataFolder : ":UserBottle:FFApp:D_C:PData:LP:App:Data"

-- inform user of process --
display dialog "
IMPORTANT:
Before running this App, please be sure you have downloaded the 'ResourcesOffline.zip', and it is in your 'Downloads' Folder.
Press [OK] when you are ready to start.
" buttons {"Ok"}

-- Set up DSResources folders in Downloads and User's Bottle --
do shell script "mkdir -p " & quoted form of (POSIX path of ExtractedFolderPath) & space & quoted form of POSIX path of {(appSupport as text) & AppName & (DataFolder as text) & ":DSResources"}

display dialog "Check! Directories in Downloads and Data" buttons {"Ok"}

-- Extract to the folder created in Downloads --
try
    do shell script "unzip -u " & quoted form of POSIX path of ((DownloadsFolder as text) & ZIPName) & " -d " & quoted form of POSIX path of ExtractedFolderPath
on error
    display dialog "
    Process failed.
    Could not find 'ResourcesOffline.zip' in 'Downloads' folder.
    Please be sure that the file exists in the specified location.
    " buttons {"Quit"} with icon 0
    if button returned of the result is "Quit" then error number -128
end try

display dialog "Check! UnZipped in MyContent" buttons {"Ok"}

-- Copy items to the folder created in Application Support --
tell application "Finder"
    set SourceFolder to folder (ExtractedFolderPath as text)
    set DestinationFolder to folder ((appSupport as text) & AppName & (DataFolder as text))
    duplicate (entire contents of first folder of SourceFolder) to DestinationFolder with replacing
    display dialog "
    All content was copied successfully. Thank you!
    " buttons {"Ok"}
end tell

display dialog "Check! All done - About to Delete TEMP Extracted files" buttons {"Ok"}

do shell script "rm -rf " & quoted form of POSIX path of ExtractedFolderPath

quit

==========================================================================

I am new to scripting, in general. Carry a basic understanding, but not much of a programmer.

I am trying to write an AppleScript script to do the following:

  1. Download 'XXX.ZIP' from 'http://MyLink.com/XXX.zip'
  2. Download in 'Downloads' folder and overwrite any existing file if it already exists
  3. Show a progress bar of the download (<- I know a progress bar is tough, so this is a nice to have
  4. Once downloaded, unpack the ZIP in same 'Downloads' location
  • Once Unzipped: I will have this (this is what is in the ZIP already):
    • One Main Folder [001]
      • One SubFolder in MainFolder [001A]
        • One File in MainFolder 001B.txt

Up till here all works fine; however from this point onwards I am struggling

  1. Copy 'All Contents' of MainFolder (not the main folder itself; just the subfolder and text file in it) from 'Downloads' folder to 'Library/Application Support/MyApp/Resources' and Replace any existing files
  2. Once copied, display popup dialogue that 'process is completed' - [OK]

Notes:

  • I am using ~/Folder locations because this script is for anyone to use, so I can't hard code the full path i.e: MacHD/Users/USERNAME/Downloads .. etc

PS - I am new to coding; so a lot of things in this code may seem 'senseless'; but I am trying so please bare with me. I have gone through a lot of forums to derive what I have but Gods of coding aren't happy with me… I am having issues trying to make all this work; this is the script I have till now:

set newFolderPath to quoted form of (expandPath("~/Downloads/MYCONTENT"))
set cmdStr to "if [[ ! -d " & newFolderPath & " ]]; then
    mkdir -m 755 " & newFolderPath & "; fi"
do shell script cmdStr
on expandPath(pPathStr)
    local fullPath
    set fullPath to pPathStr
    if fullPath = "~" then
        set fullPath to (POSIX path of (path to home folder))
    else if fullPath starts with "~/" then
        set fullPath to (POSIX path of (path to home folder)) & text 3 thru -1 of fullPath
    end if
    return fullPath
end expandPath
-- Download --  
tell application "Finder"
    do shell script "curl -L -o ~/Downloads/MYCONTENT/SOME_RESOURCES.ZIP 'https://MyWebsite.com/Stuff/DownloadableContent/SOME_RESOURCES.ZIP' > ~/Downloads/MYCONTENT/status 2>&1 &"
    set fileSize to 0
    set curTransferred to 0
    set curProgress to 0
    repeat until curProgress = "100"
        try
            set lastLine to paragraph -1 of (do shell script "cat ~/Downloads/MYCONTENT/status")
            set curProgress to word 1 of lastLine
            set fileSize to word 2 of lastLine
            set curTransferred to word 4 of lastLine
            tell me
                display dialog "Downloading; Please wait, this will take a while.
                Status: " & curTransferred & " of " & fileSize & " (" & curProgress & "%)" buttons {"Refresh", "cancel"} giving up after 5
                if the button returned of the result is "cancel" then return
            end tell
        on error
            display dialog "Download failed. To restart the download, please press the 'Retry' button" buttons {"Quit", "Retry"} with icon 0
        end try
    end repeat
    set theDialogText to "Download is complete. Press [OK] to continue"
    display dialog theDialogText
    -- Extract --
    do shell script "unzip -u  ~/Downloads/MYCONTENT/SOME_RESOURCES.ZIP -d ~/Downloads/MYCONTENT/"
    do shell script "/bin/sleep 10"
    -- ** FROM HERE ONWARDS I AM GETTING AN ERROR **
    -- Copy --
    set DownloadFolder to "~/Downloads/MYCONTENT/RESOURCES/"
    set DestinationFolder to "~/Library/Application Support/MYAPPLICATION/RESOURCES/"
    copy every file of folder (DownloadFolder's entire contents) to folder DestinationFolder
    set theDialogText to "All content has been copied. Thank you!"
    display dialog theDialogText
end tell

Solution

  • Your outline and script example are a bit different, so I went with the outline:

    • Create folders in the user's Downloads and Application Support folders as needed
    • Download a zip file to the folder created in Downloads and extract it to that folder - the zip file contains a main folder containing a sub folder (or folders) containing files
    • Copy the entire contents of the main folder to the Resources folder in the folder created in Application Support for the application

    There are a few ways to do a progress bar or download status using some AppleScriptObjC, but for better control those should probably be done from an application.

    The main problems with your script are that the Finder does not understand POSIX paths, and you missed creating the folder structure in Application Support. There are standard commands to get paths to the various system folders, so string manipulations aren't needed to get the script to work on other machines. In the following script, I keep track of the regular HFS paths, just coercing them to POSIX for the shell scripts, and added properties for the various names so they are in one spot.

    property downLoads : path to downloads folder
    property appSupport : path to application support from user domain
    property webPage : "HTTPS://MYWEBSITE.COM/STUFF/DOWNLOADABLECONTENT/"
    property webResource : "SOME_RESOURCES.ZIP" -- name for the downloaded file
    property myApp : "MYAPPLICATION" -- name for folder in Application Support (bundle identifier would be better)
    property baseName : "MYCONTENT" -- name for folder in Downloads
    property basePath : ((downLoads as text) & baseName & ":")
    
    -- Set up folders in Downloads and Application Support as needed --
    do shell script "mkdir -p " & quoted form of (POSIX path of basePath) & space & quoted form of POSIX path of ((appSupport as text) & myApp & ":Resources")
    
    -- Download and progress - more error handling is needed --  
    do shell script "curl -L " & quoted form of (webPage & webResource) & " -o " & quoted form of POSIX path of (basePath & webResource) & " > " & quoted form of POSIX path of (basePath & "status") & " 2>&1 &"
    set fileSize to 0
    set curTransferred to 0
    
    set curProgress to 0
    repeat until curProgress = "100"
       try
          set lastLine to paragraph -1 of (do shell script "cat " & quoted form of POSIX path of (basePath & "status"))
          set curProgress to word 1 of lastLine
          set fileSize to word 2 of lastLine
          set curTransferred to word 4 of lastLine
          tell me
             display dialog "Downloading; Please wait, this will take a while.
                    Status: " & curTransferred & " of " & fileSize & " (" & curProgress & "%)" buttons {"Refresh", "Cancel"} giving up after 1
             if the button returned of the result is "Cancel" then return
          end tell
       on error
          display dialog "Download failed. To restart the download, please press the 'Retry' button" buttons {"Quit", "Retry"} with icon 0
          if button returned of the result is "Quit" then error number -128
       end try
    end repeat
    display dialog "Download is complete. Press [OK] to continue"
    
    -- Extract to the folder created in Downloads --
    do shell script "unzip -u " & quoted form of POSIX path of (basePath & webResource) & " -d " & quoted form of POSIX path of basePath -- Main Folder > Sub Folder > text file
    
    -- Copy items to the folder created in Application Support --
    tell application "Finder"
       set downLoadFolder to folder basePath
       set DestinationFolder to folder ((appSupport as text) & myApp & ":Resources")
       duplicate (entire contents of first folder of downLoadFolder) to DestinationFolder with replacing -- contents of "Main Folder" -- 'duplicate' is the command to use for files
       display dialog "All content has been copied. Thank you!"
    end tell
    

    Change the placeholder items in the properties as needed - Note that the shell scripts and web file names are case sensitive.