Firstly I’m very new to applescript, please be gentle! This is in fact my first script attempt. I am testing this in script editor now but plan to put it into a Automator app. Thank you in advance for any help you can give.
I have a script I’m managed to put together from googling and this sites information and have got over most of the initial hurdles but I’m getting script error "Can’t get every paragraph of alias "Macintosh HD:Users:me:Desktop:AUTOMATOR:testfilecopy:CSVFile.csv" when I run and cannot find out why. This is just on a small test csv for now. I have a large csv that this script will eventually be used on.
The purpose is to have a small selection of source files that I need to create many duplicates from, each with a unique filename; for testing purposes. the files copies will be put into multiple new folders (for each respective test). The source list is a 3 column CSV file with sourcefilename, newfilname and newfoldername. the actual source files will be in same base folder as csv file.
Here’s my current script attempt:
set theFile to (choose file with prompt "Select the CSV file!")
set theFolderRoot to choose folder with prompt "Choose the root output folder"
set theCSVdata to paragraphs of theFile
set TID to AppleScript's text item delimiters
set AppleScript's text item delimiters to ","
repeat with row in theCSVdata
set {sourcefilename, targetfilename, targetfoldername} to text items of row
set targetfolderpath to theFolderRoot & targetfoldername
tell application "Finder"
set theFileCopy to duplicate sourcefilename to folder targetfolderpath
end tell
tell application "System Events"
set name of file theFileCopy to targetfilename
end tell
end repeat
and here is the CSV contents:
sourcefilename,targetfilename,targetfoldername
test file 1.mxf,A.mxf,folder 1
test file 2.mxf,B.mxf,folder 1
test file 3.mxf,C.mxf,folder 2
Thanks,
Mark.
Model: MBPro Retina
AppleScript: AppleScript 2.4
Browser: Chrome Version 52.0.2743.116 (64-bit)
Operating System: Mac OS X (10.10)
You have to read the file, before you can work with its text.
-------------------------------------------------------------------------------------------
set inputFileAlias to alias ((path to downloads folder as text) & "test.csv")
set theText to read inputFileAlias as «class utf8»
set theRows to paragraphs of theText
# Filter out any blank lines.
repeat with theRow in theRows
if contents of theRow = "" then
set contents of theRow to 0
end if
end repeat
set theRows to text of theRows
-------------------------------------------------------------------------------------------
But that’s not how I’d do it. I’d use the Satimage.osax to make it simpler.
-------------------------------------------------------------------------------------------
# REQUIRES the Satimage.osax AppleScript Extension “ http://tinyurl.com/dc3soh
-------------------------------------------------------------------------------------------
set inputFileAlias to alias ((path to downloads folder as text) & "test.csv")
# Find paragraphs that start with a non-space character - return as list.
set theRows to fnd("^\\S.+", inputFileAlias, true, true) of me
# Split each row (list item) using "," as the delimiter.
set theRows to fnd("[^,]+", theRows, true, true) of me
repeat with theRow in theRows
set {a, b, c} to theRow
# Etcetera
end repeat
-------------------------------------------------------------------------------------------
--» HANDLERS
-------------------------------------------------------------------------------------------
on fnd(_find, _data, _all, strRslt)
try
find text _find in _data all occurrences _all string result strRslt with regexp without case sensitive
on error
return false
end try
end fnd
-------------------------------------------------------------------------------------------
I’ve tried your first option (as that seemed easier for a complete beginner). Now I get an error “Finder got an error: Handler can’t handle objects of this class.” number -10010
which appears to be on “duplicate sourcefilename to folder targetfolderpath”
here is the current code:
set theFile to (choose file with prompt "Select the CSV file!")
set theFolderRoot to choose folder with prompt "Choose the root output folder"
set theText to read theFile as «class utf8»
set theRows to paragraphs of theText
set TID to AppleScript's text item delimiters
set AppleScript's text item delimiters to ","
# Filter out any blank lines.
repeat with theRow in theRows
if contents of theRow = "" then
set contents of theRow to 0
end if
end repeat
set theRows to text of theRows
repeat with row in theRows
set {sourcefilename, targetfilename, targetfoldername} to text items of row
set targetfolderpath to theFolderRoot & targetfoldername
tell application "Finder"
set theFileCopy to duplicate sourcefilename to folder targetfolderpath
end tell
tell application "System Events"
set name of file theFileCopy to targetfilename
end tell
end repeat
This is my first script, and I got here from taking bits of other examples and trying to fit them together to complete the purpose I need.
Is it that I need a add the full path to the source file (sourcefilename = exactly that, just the source filename) or is this taking the path that we started the CSV file in as the root for the source files?
[format] set theFileCopy to duplicate sourcefilename to folder targetfolderpath[/format]
replace it by :[format] set theFileCopy to duplicate (file sourcefilename of (the Folder containing this file) to folder targetfolderpath[/format]
I add that it woul be a good idea to insert the instruction below at the very end of your posted script.
[format]set AppleScript’s text item delimiters to TID[/format]
Yvan KOENIG running El Capitan 10.11.6 in French (VALLAURIS, France) jeudi 25 aout 2016 13:41:12
This example makes use of the AppleScript Toolbox osax (see my signature). The script assumes that the CSV file is located in the same folder as the files you want to duplicate (if not, replace the set sourceFolder. line with a choose folder command).
set theFile to (choose file with prompt "Select the CSV file!")
set theFolderRoot to choose folder with prompt "Choose the root output folder"
-- the following 4 commands require AppleScript Toolbox scripting addition
-- split the CSV file contents by linefeed and returns
set theRows to AST find regex "[^" & return & linefeed & "]+" in file theFile
-- split the lines by komma
set theData to AST find regex "[^,]+" in string theRows
-- get source folder based on basename of csv file
set sourceFolder to AST find regex ".*:" in string theFile as string
-- get a list of all file names in the source folder
set existingFiles to AST list folder sourceFolder
repeat with theRow in theData
repeat 1 times -- to simulate break later
-- check to see if CSV row is not empty or incomplete
if (count of theRow) < 3 then exit repeat --break
-- set fields to variables
set {sourceFileName, targetFileName, targetFolderName} to contents of theRow
-- check if the file exists before trying to duplicate
if sourceFileName is not in existingFiles then exit repeat --break
tell application "Finder"
set sourceFile to file ((sourceFolder as string) & sourceFileName)
set targetFolder to folder ((theFolderRoot as string) & targetFolderName & ":")
end tell
tell application "System Events"
set copiedFile to duplicate sourceFile to targetFolder
set name of copiedFile to targetFileName
end tell
end repeat
end repeat
I’ve commented this to highlight the errors and to ask about needed information.
Read through it and provide the requested info, and we’ll move forward from there.
-Chris
set theFile to (choose file with prompt "Select the CSV file!")
set theFolderRoot to choose folder with prompt "Choose the root output folder"
set theFolderRoot to theFolderRoot as text --» Change from alias to string!
set theText to read theFile as «class utf8»
set theRows to paragraphs of theText
set TID to AppleScript's text item delimiters
set AppleScript's text item delimiters to ","
# Filter out any blank lines.
repeat with theRow in theRows
if contents of theRow = "" then
set contents of theRow to 0
end if
end repeat
set theRows to text of theRows
repeat with row in theRows
set {sourcefilename, targetfilename, targetfoldername} to text items of row
set targetfolderpath to theFolderRoot & targetfoldername --» Invalid
# You cannot create intermediate folders with the duplicate command.
# Although there are ways to do it with the shell and with ASObjC.
tell application "Finder"
set theFileCopy to duplicate sourcefilename to targetfolderpath --» Invalid
# You cannot duplicate a FILE-NAME to a location.
# You have to provide a valid object-specifier.
# Where is the folder containing your source-files?
# Don't use System Events “ you're [i]already[/i] using the Finder “ stick with it.
set name of theFileCopy to targetfilename
end tell
end repeat
An tell block is only syntax for better readability to targeting multiple commands, each command is send individually to the targeted application using AppleEvents. There is nothing to stick with like in a session or something, other than personal preferences there is actually nothing wrong with it. I agree that it looks better but that is also my personal preference.
Recent experience push me to say that, although I hate Finder, when we are using it for some reasons - here to duplicate - it’s a good idea to stick on it if we want to extract filenames.
Here is why.
Assume that a file’s path is : path to desktop as text)&" a/slash.txt"
Yes I dislike slash in filenames but I am trying to help somebody with numerous filenames of this kind.
If you ask the file name to Finder, you will get “a/slash.txt”
if you ask to “System Events” you will get “a:slash.txt”
Of course if you have to build instructions using the names you will get some surprises.
set theFile to (path to desktop as text) & "a/slash.txt"
tell application "Finder"
set nameByFinder to name of file theFile
end tell
tell application "System Events"
set nameBySysEvents to name of disk item theFile
end tell
{nameByFinder, nameBySysEvents}
--> {"a/slash.txt", "a:slash.txt"}
I beg your pardon DJ, but although I’m not sure that Nigel was aware of that, given this behavior I feel that its advice was a good one.
Caution is required too if POSIX paths are used.
Yvan KOENIG running El Capitan 10.11.6 in French (VALLAURIS, France) vendredi 26 aout 2016 15:52:24
Both commands return the names correctly on my machine. VFS (BSD/Cocoa) names are converted back to virtual HFS names for AppleScript in System Events on my machine. Can you tell me on which OS the example code goes wrong?
Edit: For the record “ I’m using Mavericks and will test your code later on El Capitan (not behind a machine right now).
So System Events has the behavior of AppleScriptObjC now? which is new to me. Are some parts of System Events rewritten in Cocoa now?
I stand corrected only because of a complete different reason. It is to avoid a bug in System Events in newer systems that I mainly use not because “You’re already using Finder”.
Since the Finder is already being used to duplicate the file (returning a Finder-ref) it is inefficient to then switch to another application to rename said file.
That was my point, there is no such thing as switching to application. The tell blocks in AppleScript is just a friendly way for the coder to target multiple commands instead of using tell to for each line. AppleEvent behave pretty much like an RPC which means each event opens a connection to the target, makes a request, read the returned data en close the connection before returning the data and continuing the script. So even inside a single tell application block each AppleEvent is send individually to target application, it is not the tell that opens a connection.
On my machine it still contains a mix of deprecated code and Cocoa looking at the Mach-O executable. So some of its code require to be re-written in Cocoa instead of using the API’s on BSD Level at some point. That’s why I asked.