-- MacFileDatesChanger -- version 1.1 -- Daniel A. Shockley, http://www.danshockley.com -- Includes some code from Paul Berkowitz and Nigel Garvey on applescript-users mailing list -- Code by Dan Shockley released under a BSD license: (see http://creativecommons.org/licenses/BSD/) -- Basically, you can reuse and modify, with attribution in the source code. -- May use or download/install ChangeFileDates, an unsupported command line tool, that -- was made by HAMSoft Engineering. Read more at: -- http://www.hamsoftengineering.com/codeSharing/ChangeFileDates/ChangeFileDates.html -- Will first attempt to use SetFile, found in Apple's Developer Tools -- NOTES -- Save this script as an application to enable drag-and-drop file/folder processing -- VERSION HISTORY -- 1.1 - posted online, initial release, not all errors captured -- 1.0 - test version only property ScriptName : "MacFileDatesChanger" property dateFormatString : "%m/%d/%Y %H:%M:%S" property debugMode : false on open someItems -- someItems could be files or folders if (count of someItems) is 1 then if folder of (info for item 1 of someItems without size) then -- user dropped ONE folder on this, ask whether to modify it or contents display dialog "You dropped a single folder. Change date(s) of that Folder " &  " itself, or of its Contents?" buttons {"Cancel", "Folder", "Contents"} default button "Folder" if button returned of result is "Contents" then set oneFolder to item 1 of someItems tell application "Finder" set someItems to (items of oneFolder) as alias list end tell end if end if end if changeFileDates(someItems) end open on run set dialogMsg to "Choose a folder of files to change, or file(s)?" set buttonChoices to {"Cancel", "Folder", "Files"} set openChoice to button returned of (display dialog dialogMsg buttons buttonChoices default button "Files") if openChoice is "Files" then set chooseFileDialog to "Choose the file(s) you want to change:" set fileList to choose file with prompt chooseFileDialog with multiple selections allowed else if openChoice is "Folder" then set oneFolder to choose folder with prompt "Choose the folder whose contents (files/folders) you want to change:" tell application "Finder" set fileList to (items of oneFolder) as alias list end tell end if changeFileDates(fileList) end run on changeFileDates(fileList) set filePluralSingle to "" if (count of fileList) is greater than 1 then set filePluralSingle to "s" end if set dialogMsg to "Change Mod date, Creation date, or Both?" set buttonChoices to {"Mod", "Creation", "Both"} set dateChangeChoice to button returned of (display dialog dialogMsg buttons buttonChoices default button "Both") if dateChangeChoice is "Both" then set sameOrNot to button returned of (display dialog  "Change modification and creation to the Same or Different?" buttons  {"Cancel", "Different", "Same"} default button "Same") if sameOrNot is "Same" then set newDate to dateDialog("Please choose a new creation/mod date for the file" & filePluralSingle & ".") set newCreationDate to newDate set newModDate to newDate else -- Different, so ask for each set newCreationDate to dateDialog("Please choose a new creation date for the file" & filePluralSingle & ".") set modDateAsk to true set modDialog to "Please choose a new modification date for the file" & filePluralSingle & "." repeat while modDateAsk set newModDate to dateDialog(modDialog) if newModDate is less than newCreationDate then set modDialog to "The modification date can NOT be earlier than the creation date (" &  dateUnixFormat(newCreationDate, dateFormatString) & ")" else -- if it is not before creation, we're done set modDateAsk to false end if end repeat end if set changerPrefs to {doCreation:true, doMod:true, creationDateString:dateUnixFormat(newCreationDate, dateFormatString)}  & {modDateString:dateUnixFormat(newModDate, dateFormatString)} else if dateChangeChoice is "Creation" then set newCreationDate to dateDialog("Please choose a new creation date for the file" & filePluralSingle & ".") set changerPrefs to {doCreation:true, creationDateString:dateUnixFormat(newCreationDate, dateFormatString)} else if dateChangeChoice is "Mod" then set newModDate to dateDialog("Please choose a new modification date for the file" & filePluralSingle & ".") set changerPrefs to {doMod:true, modDateString:dateUnixFormat(newModDate, dateFormatString)} else -- should be impossible end if set cfdPosix to POSIX path of ((path to application support folder from user domain as text) &  "ChangeFileDates:ChangeFileDates") repeat with oneFilePath in fileList macFileDatesChanger(changerPrefs & {filePath:oneFilePath}) --& {binName:"ChangeFileDates", binPosix:cfdPosix}) end repeat end changeFileDates on dateDialog(dialogMsg) -- for now, just handle files, not folders set chosenDate to date (text returned of (display dialog dialogMsg  default answer my dateUnixFormat(current date, dateFormatString))) return chosenDate end dateDialog on macFileDatesChanger(prefs) -- version 1.0, Daniel A. Shockley, http://www.danshockley.com set binPrefs to getBinaryInfo({installCFD:"ASK"}) -- need to -- {binPosix:POSIX PATH TO BIN, binName:NAME OF BIN} set defaultPrefs to {doCreation:false, doMod:false, modDateString:"", creationDateString:""} & binPrefs if (class of prefs is not record) then error "macFileDatesChanger FAILED: parameter should be a single record, " &  "not just separated parameters." number 1024 end if set prefs to prefs & defaultPrefs -- add on default preferences, if needed set filePath to filePath of prefs set binPosix to binPosix of prefs set binName to binName of prefs set doCreation to doCreation of prefs set creationDateString to creationDateString of prefs set doMod to doMod of prefs set modDateString to modDateString of prefs if binName is "SetFile" then set dateOptions to "" if doCreation then set dateOptions to "-d " & quoted form of creationDateString end if if doMod then set dateOptions to dateOptions & " -m " & quoted form of modDateString end if set shellCommand to binPosix & space & dateOptions & space &  quoted form of POSIX path of filePath else if binName is "ChangeFileDates" then if not doMod or not doCreation then -- need to get EXISTING dates, since tool needs both set fileInfo to info for filePath without size set currentModDate to modification date of fileInfo set currentCreationDate to creation date of fileInfo if not doMod then set modDateString to dateUnixFormat(currentModDate, dateFormatString) if not doCreation then set creationDateString to dateUnixFormat(currentCreationDate, dateFormatString) end if set shellCommand to quoted form of binPosix &  " -cDate " & quoted form of creationDateString & " -mDate " &  quoted form of modDateString & " -file " &  quoted form of POSIX path of filePath end if try if debugMode then logConsole(ScriptName, "COMMAND: " & shellCommand) do shell script shellCommand on error theError number errorNumber display dialog "There was an error:" & return & theError & return & return &  "Error Number: " & errorNumber as text buttons {"OK"} default button 1 with icon stop end try end macFileDatesChanger on getBinaryInfo(installOptions) -- version 1.0, Daniel A. Shockley, http://www.danshockley.com -- Finds out whether SetFile is installed -- If not, looks for ChangeFileDates, by HAMSoft Engineering -- option to install set cfdPosix to POSIX path of ((path to application support folder from user domain as text) &  "ChangeFileDates:ChangeFileDates") -- Put possible places to look for binary tools into this list, first priority first set posixToTry to {"SetFile", "/Developer/Tools/SetFile", "/Developer/usr/bin/SetFile", "ChangeFileDates", cfdPosix} set foundBinPosix to tryBinPosixList(posixToTry) if length of foundBinPosix is greater than 0 then set binName to do shell script "basename " & quoted form of foundBinPosix else -- could not find it, see whether we are allowed to download and install if installCFD of installOptions is not "" then if installChangeFileDatesBinary(installOptions) then set foundBinPosix to POSIX path of ((path to application support folder from  user domain as text) & "ChangeFileDates:ChangeFileDates") set binName to "ChangeFileDates" else -- install failed or was not allowed error "Could not find a binary tool that allows creation date changing." number 1024 end if end if end if return {binPosix:foundBinPosix, binName:binName} end getBinaryInfo on tryBinPosixList(posixList) repeat with tryPath in posixList set tryPath to contents of tryPath try do shell script quoted form of tryPath on error errMsg number errNum if errNum is 1 then -- binary was found, since nonexistence is 127 return tryPath end if end try end repeat return "" end tryBinPosixList on installChangeFileDatesBinary(installOptions) -- version 1.0, Daniel A. Shockley, http://www.danshockley.com if installCFD of installOptions is "YES" then -- don't ask, just allow to continue download and install else if installCFD of installOptions is "ASK" then display dialog "No binary tool for changing dates could be found. Attempt to download " &  "and install ChangeFileDates by HAMSoft Engineering (unsupported free tool)?" buttons {" Cancel ", "Install"} if button returned of result is " Cancel " then return false display dialog "You chose to download and install ChangeFileDates. It will be placed at " &  "~/Library/Application Support/ChangeFileDates/" & return & "Please Confirm that you wish to download " &  "and install ChangeFileDates." buttons {" Cancel ", "Confirm"} default button "Confirm" if button returned of result is " Cancel " then return false else return false end if -- only should get here if user CHOSE to allow, or if installCFD was "YES" try set binaryURL to "http://www.hamsoftengineering.com/assets/ChangeFileDates.zip" set installToFolderPosix to POSIX path of ((path to application support folder from  user domain as text) & "ChangeFileDates:") set tmpZip to (do shell script "mktemp -t changefiledatesbinary") -- generate a random filepath to save zip -- (using the randomized temp-dir increases security) set curlCommand to "curl " & (quoted form of binaryURL) & space & "-o" &  space & tmpZip do shell script curlCommand set unzipCommand to "unzip " & quoted form of tmpZip & " -d " & quoted form of installToFolderPosix do shell script unzipCommand on error errMsg number errNum return false end try return true end installChangeFileDatesBinary on dateUnixFormat(theDate, unixFormatString) -- version 1.2, Daniel A. Shockley, http://www.danshockley.com -- includes code from Paul Berkowitz and Nigel Garvey on applescript-users mailing list -- updates suggested by Jonn8 on macscripter.net BBS -- dateUnixFormat DID NOT SEEM TO WORK with new Daylight Savings Time ! ! ! ! -- BUT, subtracting an hour seems to fix it. -- run 'man strftime' in a shell to read the formatting options -- basics are: %d = dd, %m = mm, %Y = yyyy, %F = %Y-%m-%d, %M = MM (minutes), %H = HH (military), %S = SS try -- get the starting Unix date as an AppleScript date set theEpoch to (date (do shell script "date -r 0 '+%a %b %e %Y %H:%M:%S'")) set unixSecs to theDate - (theEpoch) set unixSecs to unixSecs - 1 * hours -- HACK to get around bug, seemingly caused by new DST set unixSecs to my NumberToString(unixSecs) set theDate to do shell script "date -r " & unixSecs & " +" & quoted form of unixFormatString & "" on error errMsg number errNum error "dateUnixFormat FAILED: " & errMsg number errNum end try end dateUnixFormat on NumberToString(bigNumber) -- by Paul Berkowitz set bigNumber to bigNumber as string if bigNumber does not contain "E+" then return bigNumber set {tids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {"E+"}} try set {basicReal, powersOfTen} to {bigNumber's text item 1, (bigNumber's text item 2) as integer} on error -- e.g. Python strings have lower-case "e", tids case-sensitive set AppleScript's text item delimiters to {"e+"} set {basicReal, powersOfTen} to {bigNumber's text item 1, (bigNumber's text item 2) as integer} end try set AppleScript's text item delimiters to {"."} try set {integerPart, decimalPart} to basicReal's {text item 1, text item 2} set decimalSign to "." on error set AppleScript's text item delimiters to {","} set {integerPart, decimalPart} to basicReal's {text item 1, text item 2} set decimalSign to "," end try set AppleScript's text item delimiters to tids set n to count decimalPart if powersOfTen is greater than or equal to n then repeat (powersOfTen - n) times set decimalPart to decimalPart & "0" end repeat set bigNumber to integerPart & decimalPart else set bigNumber to integerPart & decimalPart set bigNumber to text 1 thru (powersOfTen + 1) of bigNumber &  decimalSign & text (powersOfTen + 2) thru -1 of bigNumber end if return bigNumber end NumberToString on logConsole(processName, consoleMsg) -- version 1.7 - Daniel A. Shockley, http://www.danshockley.com -- 1.7 - now works with Leopard by using the "logger" command instead of just appending to log file -- 1.6- the 'space' constant instead of literal spaces for readability, removed trailing space from the hostname command -- 1.5- uses standard date-stamp format set shellCommand to "logger" & space & "-t" & space & quoted form of processName & space & quoted form of consoleMsg do shell script shellCommand return shellCommand end logConsole