how do you get the long script to handle folders?
error "Can't get alias \"Untitled:_Production Drive backup 13/3/17:iTunes Media Folder:\"." number -1728 from alias "Untitled:_Production Drive backup 13/3/17:iTunes Media Folder:"
(*
rename & move mp3 ASObjC - 2
Written for http://macscripter.net/viewtopic.php?id=45629
by Nigel GARVEY, Shane STANLEY & Yvan KOENIG
2017/04/15
Tested under 10.12.4 public version
# Edited on 2017/04/18 : report the list of files which weren't moved
# Edited on 2017/04/19 : at Nigel GARVEY's request, removed some instructions
CAUTION. THE SCRIPT IS SUPPOSED TO RENAME AND MOVE SOME FILES.
IF YOU ARE NOT SURE OF WHAT IT DOES, EDIT THE PROPERTY NAMED testIt SETTING IT THE VALUE : true
*)
use AppleScript version "2.4" # requires at least Yosemite
use scripting additions
use framework "Foundation"
property copyString : " #" -- added to file names for copies; edit to suit your language
property destinationRootPath : "/Volumes/Production/test/" # I assume that it's the one you need
property testIt : false
#################### true = log some metadatas and DON'T MOVE the files
#################### false = don't log these metadatas and MOVE the files
on run -- For when testing.
set theFiles to choose folder with prompt "Please select folder"
mainBusiness(theFiles)
end run
on adding folder items to thisFolder after receiving addedItems -- For when run as a folder action.
mainBusiness(addedItems)
end adding folder items to
on mainBusiness(theFiles)
-- Get the root path in a convenient form for use with ASObjC.
local destinationRootPath, |⌘|
# Instructions useful to get a script running flawlessly on my machine!
set run4YK to (path to home folder as text) starts with "SSD 500"
if run4YK then
set my destinationRootPath to "/Volumes/Production/test3"
set my testIt to true
end if
set |⌘| to current application
set newArray to |⌘|'s NSMutableArray's arrayWithArray:{}
set destinationRootPath to |⌘|'s class "NSString"'s stringWithString:(my destinationRootPath)
repeat with thisFile in theFiles
set thePath to POSIX path of thisFile
set thePath to (|⌘|'s NSString's stringWithString:thePath)
set theExtension to thePath's pathExtension()
set theName to thePath's lastPathComponent()
set theContainer to thePath's stringByDeletingLastPathComponent()
set thePred to |⌘|'s NSPredicate's predicateWithFormat_("kMDItemFSName == %@", theName)
-- build and start query
set theQuery to |⌘|'s NSMetadataQuery's new()
(theQuery's setPredicate:thePred)
(theQuery's setSearchScopes:{theContainer})
theQuery's startQuery()
-- loop until it's stopped gathering
repeat while theQuery's isGathering() as boolean
delay 0.1
end repeat
-- stop and get the first NSMetadataItem (there can only be one in this case)
theQuery's stopQuery()
set metaItem to (theQuery's resultAtIndex:0)
-- get the required attribute values, or default alternatives where the attributes weren't found.
-- Firstly the artist ("authors") and genre values.
set theArtist to (metaItem's valueForAttribute:(|⌘|'s NSMetadataItemAuthorsKey))
set moveItArtist to (theArtist is not missing value)
if (theArtist is missing value) then
set theArtist to "(no artist)"
else
set theArtist to (theArtist's componentsJoinedByString:(","))
set theArtist to my decodeText(theArtist)
end if
set theGenre to (metaItem's valueForAttribute:(|⌘|'s NSMetadataItemMusicalGenreKey))
set moveItGenre to (theGenre is not missing value) # MOVED
if (theGenre is missing value) then set theGenre to "(no genre)"
-- Get the key, tempo, and title values.
set theKey to (metaItem's valueForAttribute:(|⌘|'s NSMetadataItemKeySignatureKey))
set moveItKey to (theKey is not missing value) # MOVED
if (theKey is missing value) then set theKey to "(no key signature)"
set theTempo to (metaItem's valueForAttribute:(|⌘|'s NSMetadataItemTempoKey))
set moveItTempo to (theTempo is not missing value)
# Instructions useful to get a script running flawlessly on my machine!
if run4YK then
# Here theKey metadata is NEVER defined so this instruction forbid every move.
--set moveForbidden to (moveItArtist is false) or (moveItGenre is false) or (moveItKey is false)
# With this one move is often allowed
set moveForbidden to (moveItArtist is false) or (moveItGenre is false)
else
# The test below matches what you asked in the thread
# If one of the four flags is false we don't move the file.
set moveForbidden to (moveItArtist is false) or (moveItGenre is false) or (moveItKey is false) or (moveItTempo is false)
end if
if moveForbidden then
log "Don't move : " & thePath & linefeed & "because at least one of these flags is false --> moveItArtist = " & moveItArtist & ", moveItGenre = " & moveItGenre & ", moveItKey = " & moveItKey & ", moveItTempo = " & moveItTempo # don't move the file
(newArray's addObject:thePath)
else
-- Derive a path to the destination folder from the root path, genre, and artist.
set destinationFolderPath to destinationRootPath's stringByAppendingFormat_("%@/%@", theGenre, theArtist)
-- Create the folder, if necessary.
my createFolder(destinationFolderPath) -- as text)
set theTitle to (metaItem's valueForAttribute:(|⌘|'s NSMetadataItemTitleKey))
if (theTitle is missing value) then
--set theTitle to "(no title)"
-- Derive a destination path for the file with a new name made up from these details.
# but replace theTtle by the original fileName
set destinationFileName to (|⌘|'s NSString's stringWithFormat_("%@-%@ %@", theTempo, theKey, theName))
else
# CAUTION, if the original title contained underscores they are replaced by slashes in theTitle.
# We must revert that
set theTitle to (theTitle's stringByReplacingOccurrencesOfString:"/" withString:"_")
-- Derive a destination path for the file with a new name made up from these details.
set destinationFileName to (|⌘|'s NSString's stringWithFormat_("%@-%@ %@.%@", theTempo, theKey, theTitle, theExtension))
end if
if not testIt then
# Move the file to the new destination. It'll be renamed in the process.
# DISABLED DURING TESTS
(my moveThisFile:thePath uniquelyToPath:destinationFolderPath newName:destinationFileName)
else
log (get destinationFolderPath as text) & ", " & destinationFileName
log "theArtist (Authors) : " & theArtist
log "theTitle : " & theTitle
log "theGenre : " & theGenre
if theKey is not missing value then log "theKey : " & theKey
end if # not testIt
end if # (moveItTitle .
end repeat
if (newArray's |count|()) as integer > 0 then
set outDoc to (newArray's componentsJoinedByString:linefeed)
set outPath to (path to desktop as text) & "report Mp3_3pMtroper.txt"
set outPath to (|⌘|'s NSString's stringWithString:(POSIX path of outPath))
set theResult to outDoc's writeToFile:outPath atomically:true encoding:(current application's NSUTF8StringEncoding) |error|:(missing value)
end if
end mainBusiness
#=====
-- Creates a new folder. There is no error if the folder already exists, and it will also create intermediate folders if required
on createFolder(POSIXPath)
log "PosixPath : " & POSIXPath
set |⌘| to current application
set theFolderURL to |⌘|'s |NSURL|'s fileURLWithPath:POSIXPath
set theFileManager to |⌘|'s NSFileManager's defaultManager()
set {theResult, theError} to theFileManager's createDirectoryAtURL:theFolderURL withIntermediateDirectories:true attributes:(missing value) |error|:(reference)
if not (theResult as boolean) then error (theError's |localizedDescription|() as text)
end createFolder
# Called with sourceString defined as NSString
on replaceSeveralStrings:sourceString existingStrings:listOfExistingStrings newStrings:listOfNewStrings
if (count listOfExistingStrings) > (count listOfNewStrings) then error "The first list of strings is longer than the second one !" number 1789
--set sourceString to current application's NSString's stringWithString:sourceString
repeat with i from 1 to count listOfExistingStrings
set sourceString to (sourceString's stringByReplacingOccurrencesOfString:(listOfExistingStrings's item i) withString:(listOfNewStrings's item i))
end repeat
return sourceString as text
end replaceSeveralStrings:existingStrings:newStrings:
# Called with sourceString defined as NSString
on decodeText(theText) # Handler written by Nigel GARVEY
set |⌘| to current application
--set theText to |⌘|'s class "NSString"'s stringWithString:(theText)
-- If the string contains at least two consecutive 8+bit characters, assume it's a mangled result.
if ((theText's rangeOfString:("[\\u0080-\\U0010ffff]{2}") options:(|⌘|'s NSRegularExpressionSearch))'s |length|() > 0) then
set dataObj to (theText's dataUsingEncoding:(|⌘|'s NSISOLatin1StringEncoding))
set theText to (|⌘|'s class "NSString"'s alloc()'s initWithData:(dataObj) encoding:(|⌘|'s NSUTF8StringEncoding))
end if
return theText as text
end decodeText
# Modified version of a Shane STANLEY's handler borrowed from File Manager.scptd
on moveThisFile:aFileOrPath uniquelyToPath:folderOrPath newName:destName
# makes a NSURL from aFileOrPath
set theSourceURL to my makeURLFromFileOrPath:aFileOrPath
# makes a NSURL from folderOrPath
set theFolderURL to my makeURLFromFileOrPath:folderOrPath
# Drops the name extension from the proposed name
set destNameLessExt to destName's |stringByDeletingPathExtension|()
set theExtension to theSourceURL's |pathExtension|()
# Builds the URL pointing to the final file
set theDestURL to theFolderURL's URLByAppendingPathComponent:destName
set theFileManager to current application's NSFileManager's |defaultManager|()
set i to 2
repeat
set {theResult, theError} to (theFileManager's moveItemAtURL:theSourceURL toURL:theDestURL |error|:(reference))
if theResult as boolean then exit repeat
if (theError's code() as integer = current application's NSFileWriteFileExistsError as integer) then -- it already exists, so change name
set proposedName to (destNameLessExt's stringByAppendingString:(copyString & i))'s stringByAppendingPathExtension:theExtension
set theDestURL to theFolderURL's URLByAppendingPathComponent:proposedName
set i to i + 1
else -- an error other than file already exists, so return error
error (theError's |localizedDescription|() as text)
end if
end repeat
-- return theDestURL's |path|() as text
end moveThisFile:uniquelyToPath:newName:
# Shane STANLEY's handler borrowed from File Manager.scptd
-- This handler is called by moveItem
on makeURLFromFileOrPath:theFileOrPathInput
set |⌘| to current application
-- make it into a Cocoa object for easier comparison
set theFileOrPath to item 1 of (|⌘|'s NSArray's arrayWithObject:theFileOrPathInput)
if (theFileOrPath's isKindOfClass:(|⌘|'s NSString)) as boolean then
if (theFileOrPath's hasPrefix:"/") as boolean then -- full POSIX path
return |⌘|'s class "NSURL"'s fileURLWithPath:theFileOrPath
else if (theFileOrPath's hasPrefix:"~") as boolean then -- POSIX path needing ~ expansion
return |⌘|'s class "NSURL"'s fileURLWithPath:(theFileOrPath's |stringByExpandingTildeInPath|())
else -- must be HFS path
return |⌘|'s class "NSURL"'s fileURLWithPath:(POSIX path of theFileOrPathInput)
end if
else if (theFileOrPath's isKindOfClass:(|⌘|'s class "NSURL")) as boolean then -- happens with files and aliases in 10.11
return theFileOrPath
else -- must be a file or alias
return |⌘|'s class "NSURL"'s fileURLWithPath:(POSIX path of theFileOrPathInput)
end if
end makeURLFromFileOrPath: