I'm trying to make a script that will do this:
There will be a .txt file with a list of names, one per paragraph, like this:
name1
name2
name3
name4
name5
There also will be a folder with lots of files in it.
I want the script to look at every file in that folder, and in any of the names listed in .txt file are contained in the file name, then move that file to a specific folder. If the file name does not contain one of the names from the list, then move that file to a different folder.
Example:
- There are "name1", "name2" and "name3" in the .txt file.
- There are "000name2000.jpg", "000name7000.jpg" and "000name3000.jpg" in the folder.
- "000name2000.jpg" contains "name2" in it so it should be moved to folder1.
- "000name3000.jpg" should be moved to folder1 as well.
- And "000name7000.jpg" should be moved to folder2.
I want it to be so because this list with names will be very long and I want script to be as small as possible.
This is how my script looks like now:
property source_folder : alias "path:to:source_folder"
property tattoos_folder : alias "path:to:first_folder"
property models_folder : alias "path:to:second_folder"
property text_file : alias "path:to:text_file.txt"
process_folder(source_folder)
on process_folder(this_folder)
set these_items to list folder this_folder without invisibles
set container_name to name of (info for this_folder)
repeat with i from 1 to the count of these_items
set this_item to alias ((this_folder as Unicode text) & (item i of these_items))
if folder of (info for this_item) is true then
process_folder(this_item)
else
process_item(this_item, container_name, i)
end if
end repeat
end process_folder
on process_item(this_item, c, i)
if i < 10 then
set i to "000" & i
else if (i < 100) and (i > 9) then
set i to "00" & i
else if (i < 1000) and (i > 99) then
set i to "0" & i
end if
set r to (random number from 0 to 9999)
if r < 10 then
set r to "000" & r
else if (r < 100) and (r > 9) then
set r to "00" & r
else if (r < 1000) and (r > 99) then
set r to "0" & r
end if
tell application "System Events"
-- get file extension so not overwritten
set e to name extension of this_item
set new_name to "" & r & "" & c & "" & i & "." & e
set name of this_item to new_name
move this_item to first_folder -- THIS IS WHERE THIS NEW PART OF CODE SHOULD BE
end if -- IF NAME IS (meets name from .txt file) THEN MOVE TO first_folder,
end tell -- IF ANOTHER THEN MOVE TO second_folder
end process_item
display notification "All images were processed." with title "New" sound name "Glass.aiff"
tell me to quit
This assumes you can define your text file and folder paths in the script. You can add choose dialogs if you need to.
This script puts all files in the source folder into a list, then it goes through each file, checking if a name in the name list matches, and if it does, moves it to folder1, otherwise, if it is still left after checking all the names, then moves it to folder2.
-- define folder/file locations
property nameFile : ((path to desktop) & "nameList.txt") as string
property sourceFolder : ((path to desktop) & "test:") as string
property folder1 : ((path to desktop) & "folder1:") as string
property folder2 : ((path to desktop) & "folder2:") as string
try
set move1List to {}
set move2List to {}
set nameList to paragraphs of (read file nameFile)
set fileList to list folder sourceFolder without invisibles
repeat with n from 1 to count (fileList)
set thisFile to item n of fileList
-- set fileName to name of (info for alias (sourceFolder & thisFile))
set fileRef to alias (sourceFolder & thisFile)
repeat with thisName in nameList
if (thisName as string) is in thisFile then
set end of move1List to fileRef
exit repeat
end if
end repeat
if exists fileRef then set end of move2List to fileRef
end repeat
display dialog "About to move: " & return & (count move1List) & " files to folder1" & return & (count move2List) & " files to folder2"
-- move all the files in the lists
tell application "Finder" -- can try "System Events"
move move1List to folder folder1
move move2List to folder folder2
end tell
-- could avoid Finder by iterating to a shell script using
-- do shell script "mv " & quoted form of thisFile & space & quoted form of folder1
on error err
display dialog err
end try
Related
I am writing an AppleScript to handle some MTS files. The script recursively iterates through the subfolders of the top-level folder "Volumes:G-Drive:video". The subfolders are arranged into year folders, starting with the folder named "2005" for the year 2005. The runtime error is occurring with the very first folder "2005" that the script tries to iterate. I suspected it is something to do with how I am handling aliases and text, but I am stumped at this point how to fix it. The error at runtime is this:
Can’t make {alias "G-DRIVE:video:", "2005:"} into type integer.
I don't know where in my code an integer type comes into play so as to get this error. Script Editor doesn't point me to the location of the runtime error in the code, so i don't know how to figure out which line is causing this either.
set folderName to "Volumes:G-Drive:video" as alias
my processFolder("", folderName)
on processFolder(root, folderNameToProcess)
tell application "Finder"
set theItems to every file of folder (root & folderNameToProcess)
repeat with theFile in theItems
set Nm to name of theFile as text
set Ex to name extension of theFile
if Nm does not contain "-c" and Ex is "MTS" then
set NmMinusExt to my remove_extension(Nm)
set logMsg to "Deleting " & Nm
my logThis(logMsg)
tell application "Finder" to delete theFile
end if
end repeat
set theItems to every file of folder (root & folderNameToProcess)
repeat with theFile in theItems
set Nm to name of theFile as text
set Ex to name extension of theFile
--tell (info for theFile) to set {Nm, Ex} to {name, name extension}
if Nm contains "-c" and Ex is "MTS" then
set NmMinusExt to my remove_extension(Nm)
set shortNm to my remove_lastTwoCharacters(NmMinusExt)
set name of theFile to shortNm & ".MTS" as text
set logMsg to "Renaming " & Nm
my logThis(logMsg)
--set lastTwoLetters to characters (((length of Nm) - 2) as number) thru (((length of Nm) - 0) as number) of (Nm as text)
--if lastTwoLetters is "-c" then
--display notification lastTwoLetters
--end if
end if
end repeat
set theFolders to name of folders of folder (root & folderNameToProcess)
repeat with theFolder in theFolders
copy theFolder as string to TheFolderName
display notification "found folder named: " & TheFolderName
set firstChar to (text 1 thru 1 of TheFolderName)
if firstChar is not "." then
--display dialog (folderNameToProcess & TheFolderName & ":")
try
my processFolder(folderNameToProcess, TheFolderName & ":")
on error errStr number errorNumber
display dialog errStr
end try
end if
end repeat
end tell
return
end processFolder
on remove_extension(this_name)
if this_name contains "." then
set this_name to ¬
(the reverse of every character of this_name) as string
set x to the offset of "." in this_name
set this_name to (text (x + 1) thru -1 of this_name)
set this_name to (the reverse of every character of this_name) as string
end if
return this_name
end remove_extension
on remove_lastTwoCharacters(this_name)
set this_name to ¬
(the reverse of every character of this_name) as string
set this_name to (text 3 thru -1 of this_name)
set this_name to (the reverse of every character of this_name) as string
return this_name
end remove_lastTwoCharacters
The Events pane of Script Editor produces the following trace:
tell application "Finder"
get every file of folder "G-DRIVE:video:"
get every file of folder "G-DRIVE:video:"
get name of every folder of folder "G-DRIVE:video:"
display notification "found folder named: 2005"
end tell
tell application "Script Editor"
display notification "found folder named: 2005"
end tell
tell application "Finder"
get every file of folder {alias "G-DRIVE:video:", "2005:"}
display dialog "Finder got an error: Can’t make {alias \"G-DRIVE:video:\", \"2005:\"} into type integer."
folderName is an alias. The attempt to concatenate an alias and a string creates a list which the error indicates.
The solution is to use only (HFS) string paths.
Replace
set folderName to "Volumes:G-Drive:video" as alias
with
set folderName to "G-Drive:video:"
The trailing colon is crucial to be able to add path components
I have found similar solutions like this:
property theOpenFile : missing value
tell application "Finder" to set theSel to selection
if theSel is not {} then
set pathToYourTextFile to (path to desktop folder as string) & "SampleTextFile2.txt"
set theOpenFile to open for access file (pathToYourTextFile as string) with write permission
repeat with aItem in theSel
tell application "Finder" to class of aItem is folder
if the result then my getFilesIn(aItem) -- aItem is a folder
end repeat
close access theOpenFile
end if
on getFilesIn(thisFolder)
tell application "Finder" to set theseFiles to files of thisFolder as alias list
repeat with thisFile in theseFiles
set f to thisFile as string
set pathLength to length of f
if pathLength > 255 then my writeToFile(f)
end repeat
tell application "Finder" to set theseSubFolders to folders of thisFolder
repeat with tSubF in theseSubFolders
my getFilesIn(tSubF) -- call this handler (recursively through this folder)
end repeat
end getFilesIn
on writeToFile(t)
write (t & return) to theOpenFile starting at eof
end writeToFile
They all work in with a file reference in alias format. As I understand I cannot change the filename of the original in this case, or delete it, etc. and thats what I want to do.
Am I right ? If yes what else can I do ?
You can rename and delete files, the Finder can handle alias specifiers
repeat with thisFile in (get theseFiles) -- you need get to capture the reference list
set f to thisFile as string
set pathLength to length of f
if pathLength > 255 then my writeToFile(f)
tell application "Finder" to set name of thisFile to "foo.txt"
-- or
tell application "Finder" to delete thisFile
end repeat
or rather than an alias you can use Finder file specifiers
repeat with thisFile in (get theseFiles)
set f to thisFile as string
set pathLength to length of f
if pathLength > 255 then my writeToFile(f)
tell application "Finder" to set name of file f to "foo.txt"
-- or
tell application "Finder" to delete file f
end repeat
Still a Noob / novice here
So I am trying to rename a file within a folder
set newfoldername to DT & "-" & JobName & " - " & Wedding --Adds Date, Couples name and event type to make directory name
MORE CODE HERE
set destFolder to loc & newfoldername & ":Final Delivery:DVD:"
tell application "Finder"
duplicate file sourcedvdtemp to folder destFolder
set the name of file "DVD_template.dspproj" to newfoldername
end tell
But I just get an error
"error "Finder got an error: Can’t set file \"DVD_template.dspproj\" to \"newfoldername.dspproj\"." number -10006 from file "DVD_template.dspproj""
I have tried various ways, with and without the extension "newfoldername" is set above and creates a folder with the users input as a name
Am I just being stupid or have I missed something completely.
EDIT
tell application "Finder" to set frontmost to true
set DT to text returned of (display dialog "Please enter the wedding date" default answer "YYYY/MM/DD") --Asks for date of wedding
set JobName to text returned of (display dialog "Please enter the couples name" default answer "Bride & Groom + Surname") --Asks for couples name
set Wedding to text returned of (display dialog "Please enter the type of day" default answer "Wedding") --Asks for type of day, Wedding, Party, etc
--Creates directory with info from above
set loc to (choose folder "Please choose where you would like to save the files") as text --Loc = Location of where directory will be placed
set newfoldername to DT & "-" & JobName & " - " & Wedding --Adds Date, Couples name and event type to make directory name
set folderStructure to "/{Audio/{Music,RAW\\ Audio\\ Cards},Documents,Exports,FCPX\\ Library,Film\\ Poster,Final\\ Delivery/{DVD,USB,WEB},Images/{Graphics,Stills},RAW\\ Cards/{C100-1,C100-2,7D,100D},XML}"
do shell script "mkdir -p " & quoted form of POSIX path of (loc & newfoldername) & folderStructure
set sourcedvdtemp to (path to movies folder as text) & "## - WeddingTemplate - ##:DVD_template.dspproj" --Gets file DVD_template
set sourceusbtemp to (path to movies folder as text) & "## - WeddingTemplate - ##:USB_template.zip" --Gets file USB_template
set sourcewebtemp to (path to movies folder as text) & "## - WeddingTemplate - ##:WEB_template.zip" --Gets file WEB_template
set sourcefcpxtemp to (path to movies folder as text) & "## - WeddingTemplate - ##:FCPX_template.fcpbundle" --Gets file FCPX_template
set sourcefilmpostemp to (path to movies folder as text) & "## - WeddingTemplate - ##:FILM_POSTER_Template.psd" --Gets file FILM_POSTER_template
set destFolder to loc & newfoldername & ":Final Delivery:DVD:"
tell application "Finder"
duplicate file sourcedvdtemp to folder destFolder
set the name of file "DVD_template.dspproj" to newfoldername
end tell
set destFolder to loc & newfoldername & ":FCPX Library:"
tell application "Finder"
duplicate file sourcefcpxtemp to folder destFolder
set the name of file "FCPX_template.fcpbundle" to newfoldername
end tell
set destFolder to loc & newfoldername & ":Film Poster:"
tell application "Finder"
duplicate file sourcefilmpostemp to folder destFolder
set the name of file "FILM_POSTER_Template.psd" to newfoldername
end tell
You are trying to rename a file "DVD_template.dspproj" on desktop which obviously does not exist. The desktop folder is the root folder of the Finder.
The duplicate command of the Finder returns the duplicated file so it's simply
tell application "Finder"
set fileExtension to name extension of file sourcedvdtemp
set duplicatedFile to duplicate file sourcedvdtemp to folder destFolder
set name of duplicatedFile to newfoldername & "." & fileExtension
end tell
If you want to rename the file to newfoldername you have to copy and add the file extension.
PS: Instead of calculating the template folder 5 times I recommend to write
set weddingTemplateFolder to (path to movies folder as text) & "## - WeddingTemplate - ##:"
set sourcedvdtemp to weddingTemplateFolder & "DVD_template.dspproj" --Gets file DVD_template
set sourceusbtemp to weddingTemplateFolder & "USB_template.zip" --Gets file USB_template
... etc.
I'm confused - I've been googling for an hour and have tried probably ten different forms of set posixDirectory to POSIX path of (parent of (path to aFile) as string) but I can't seem to get it right.
I'm getting the full POSIX path (including the filename) by doing
set posixFilePath to POSIX path of aFile
Now, how do I get the POSIX path of just the directory?? I'm getting various errors depending on what I do... can't make alias.. can't get parent of alias...
I would think this should work but it's not...
set posixDirectory to POSIX path of ((parent of aFile))
There are couple of ways to do this if you already have the initial path.
From Posix path format
set thePath to "/Users/USERNAME/Documents/Test/selectedTextColour.css"
set textNumber1 to characters 1 thru -((offset of "/" in (reverse of items of thePath as string)) + 1) of thePath as string
or using shell
set thePath to "/Users/USERNAME/Documents/Test/selectedTextColour.css"
set parentPath to do shell script "dirname " & quoted form of thePath
Result: "/Users/USERNAME/Documents/Test"
From Posix file format
set thePath to "Macintosh HD:Users:USERNAME:Documents:Test:selectedTextColour.css"
set textNumber1 to characters 1 thru -((offset of ":" in (reverse of items of thePath as string)) + 1) of thePath as string
Result: "Macintosh HD:Users:USERNAME:Documents:Test"
Use the container command of Finder:
set aFile to choose file
tell application "Finder" to set posixDirectory to POSIX path of ((container of aFile) as text)
This should be sufficient really, when you already have the posix path of a file.
to parentFolOfPxPath for pxPath
-- Assumes no superfluous slashes
set {tids, text item delimiters, i} to {text item delimiters, "/", ((pxPath ends with "/") as integer) + 1}
set {parFol, text item delimiters} to {text 1 thru text item -(i + 1) of pxPath, tids}
return parFol
end parentFolOfPxPath
Try the subroutine parentFolderOf(localPath). localPath can be an alias, alias as text or a posix path. It returns a reference that you can use with Finder, like this:
set thisItem to parentFolderOf(path to fonts folder)
tell application "Finder" to reveal thisItem
Here the script:
log (path to fonts folder)
log parentFolderOf(path to fonts folder)
log parentFolderOf(POSIX path of (path to fonts folder as text)) as text
log parentFolderOf("/System")
log parentFolderOf("/System") as text
# lets generate an error:
# parentFolderOf("ThisGeneratesAnError")
on parentFolderOf(localPath)
if (class of localPath is text) and (localPath contains ":") then
try
set localPath to localPath as alias
on error
error "File missing!"
end try
end if
# if its not an alias and not text containing ":" we assume its a posix path
if not (class of localPath is alias) then
try
set localPath to (localPath as POSIX file) as alias
on error
error "File missing!"
end try
end if
-- get the container:
set localPathContainerPath to ""
tell application "Finder"
try
set localPathContainerPath to (get container of localPath)
end try
end tell
return localPathContainerPath
end parentFolderOf
Addition McUsr's approach seems to be a good strategy because there is no need to use Finder (which will throw an error if the item is missing). Here a version whose input works with alias, (alias as text) or posix path:
log (parentFolder for (path to me))
log (parentFolder for "/Root/Sub1/Sub2/Sub3/testFile.txt")
log (parentFolder for "/Root/Sub1/Sub2/Sub3////")
log (parentFolder for "///Root/Sub1/Sub2/Sub3////")
log (posixPath for (path to me))
to parentFolder for aPath
set aPath to posixPath for aPath
set {tids, text item delimiters, i} to {text item delimiters, "/", ((aPath ends with "/") as integer) + 1}
set {pF, text item delimiters} to {text 1 thru text item -(i + 1) of aPath, tids}
return pF
end parentFolder
to posixPath for aPath
if class of aPath is not text then set aPath to aPath as text
if aPath contains ":" then set aPath to POSIX path of aPath
repeat while aPath starts with "//"
set aPath to (characters 2 thru -1 of aPath) as text
end repeat
repeat while aPath ends with "//"
set aPath to (characters 1 thru -2 of aPath) as text
end repeat
return aPath
end posixPath
Code snippet:
tell application "Finder" to set new_item to ¬
(container of this_item as string) & (name of this_item) & "s"
save this_image in new_item as typ
Its saving the file as filename.pngs I want it to save as filenames.png. Any ideas how to fix this?
Save this as an application, then you can drop things on it and it will copy them adding an s to the name. Or you can double-click it and it will ask you to choose a file to copy. NOTE: change the property appendText if you want to change the text (i.e. "s") that's added to the name.
Notice the handler getName_andExtension(f). That's what I use to get the name and extension from a file. I use that to calculate the new path when adding the s.
I hope that helps!
property appendText : "s"
on run
set f to choose file
duplicateInPlace_appendingText(f, appendText)
end run
on open the_items
repeat with f in the_items
duplicateInPlace_appendingText(f, appendText)
end repeat
end open
on duplicateInPlace_appendingText(f, textToAppend)
set f to f as text
set {nm, ex} to getName_andExtension(f)
tell application "Finder" to set theContainer to (container of item f) as text
if ex is "" then
set new_path to theContainer & nm & textToAppend
else
set new_path to theContainer & nm & textToAppend & "." & ex
end if
do shell script "cp -R " & quoted form of POSIX path of f & space & quoted form of POSIX path of new_path
end duplicateInPlace_appendingText
on getName_andExtension(f)
set f to f as text
set {name:nm, name extension:ex} to info for file f without size
if ex is missing value then set ex to ""
if ex is not "" then
set nm to text 1 thru ((count nm) - (count ex) - 1) of nm
end if
return {nm, ex}
end getName_andExtension
name of this_item gives the full name of the Finder item, including the file extension. You need to split it up. Unfortunately, this isn't as easy as it could be. You could do something like:
tell application "Finder"
get the selection
set {dispname, ext, exthidden} to {displayed name, name extension, extension hidden} of item 1 of the result
end tell
if exthidden then
dispname & "s." & ext
else
((characters 1 through -(2 + (count of ext)) of dispname) as string) & "s." & ext
end if
That just builds the modified name for the first item in the Finder selection, without doing anything with it.