Selecting and Moving Files

I am totally new to AppleScript, i want to write a script that does the following

  1. Ask user to select a folder from the network (Assuming disk is already mounted)
  2. Delete all the fonts from the fonts folder within the systems folder in the local Mac
  3. Select all the fonts within that folder from the network and copy it into the fonts folder within the local machine.

I have just started to get into AppleScript and i have absolutely no idea of how to go about solving this.

Thanks in advance and please excuse if i have posted this in the wrong section

Model: IMac
Browser: Firefox 1.5.0.4
Operating System: Mac OS X (10.4)

I’ve done this so far


On run
	set folder_path to "MAC18:transfer"
	try
		display dialog "Are you sure you want to delete all the files in the folder?"
		tell application "Finder" to delete every file of folder folder_path
	on error
		beep 2
	end try
        tell application "Finder" activate
		
 set rpath to "SERV:General:Users:Shyam:"
			
set myReply to text returned of (display dialog "Enter Job No" default answer "Job")
set f3 to rpath & myReply 
set f4 to "MAC18:transfer"

tell application "Finder"
			copy every file of folder f3 to folder f4
		end tell
	end tell
end run

It works. When i run the script it asks me if i need to delete the specied folder and then asks for the name of the folder from which it should be copied. Once given it copies all the files from the specified folder and drops it into the local folder.

Is this the right way to do it?. This is my first script in AppleScript and i would really appreciate it if someone can review it and give me some feedback.

I think it looks pretty good for a first time script, kshyam. I have a few recommendations:


on run
	set folder_path to "MAC18:transfer:" --It is always a good idea to use a colon when referencing a folder
	try
		display dialog "Are you sure you want to delete all the files in the folder?"
		tell application "Finder" to delete every file of folder folder_path
	on error
		beep 2
	end try
	--tell application "Finder" activate --This is not needed
	
	set rpath to "SERV:General:Users:Shyam:"
	
	set myReply to text returned of (display dialog "Enter Job No" default answer "Job")
	set f3 to rpath & myReply & ":" --Same thing here, use a colon at the end to indicate a folder
	--set f4 to "MAC18:transfer" --This is not needed, since you alreaded set the variable folder_path to the same thing earlier in the script.
	
	tell application "Finder"
		copy every file of folder f3 to folder folder_path
	end tell
	--end tell --This is not needed
end run

Incidentally, I could not get your script to compile until I removed the [tell application “Finder” activate] block, which is fine, since you don’t need it. It is good practice to only tell the Finder to do something that only it can do, like the deleting and moving files as you have here. Also, as I indicated in the script comments, it is also a good idea to use a colon at the end of a string that refers to a folder, just in case the Finder is having a bad day, it keeps things clean.

I hope this helps.

Thanks a lot Craig Smith.
It really helps to learn how to optimize code. Thanks again.

hi With reference to my 1st post. I was thinking of making a few modification, instead of deleting all the files in the local folder i was thinking of moving them to a seperate area within the local disk into a folder with the current date& time(the hour alone) eg a folder named ‘2006-07-24 12-28’ if i do it now.

is this possible? or am i just crazy

You can assemble a sortable time stamp string: yr-mo-day-hr-min, with this handler. The name of the folder you create would then be set to makeStamp:

to makeStamp(Now, delim)
	set d to delim -- whatever you want between the numbers
	tell Now to tell 100000000 + day * 1000000 + (its month) * 10000 + year as string ¬
		to set dateStamp to text -2 thru -1 & d & text 4 thru 5 & d & text 2 thru 3
	tell Now to tell ((10000 + (its hours) * 100 + (its minutes)) as string) ¬
		to set timeStamp to text 2 thru 3 & d & text 4 thru 5
	return dateStamp & d & timeStamp
end makeStamp

set Now to (current date) -- any date including (current date)
set myFolder to makeStamp(Now, ".") --> "06.07.24.13.17"

Thanks Adam,

I really learnt a lot with this.
Thanks again.

Taking pity on you for that highly compressed but fast way of getting a time stamp, here’s a script that does what it does in a different (and much more obvious) way. The other is a clever way due originally to Nigel Garvey and contributed to by Kai, for getting two characters for each part by adding them to a large number after multiplying them by a constant that shifts them to the right decimal position.

makeTimeStamp((current date), ".")

-- aDelim should be one character of text
to makeTimeStamp(aDate, aDelim)
	-- Get our pieces
	tell aDate -- to avoid having to repeat "of aDate" in every line, replacing it with "its".
		set yr to its year
		set mo to its month as number
		set dy to its day
		set hr to its hours
		set mn to its minutes
		set sc to its seconds
	end tell
	-- Build our stamp
	set TS to "" -- initialize our output string to an empty string
	--return {yr, mo, dy, hr, mn, sc} -- uncomment to see the values of the parts
	repeat with D in {yr, mo, dy, hr, mn, sc} -- adjust each of the parts to be two characters
		if length of ((contents of D) as text) < 2 then set contents of D to "0" & D -- stick a "0" in front of single.
		set TS to TS & D & aDelim -- add this piece to the rest (called concatination)
	end repeat
	return characters 3 thru -2 of TS as string -- skip the "20", and the final "aDelim character".
end makeTimeStamp

In slightly more compressed form:

makeTimeStamp((current date), ".")

-- aDelim should be one character of text
to makeTimeStamp(aDate, aDelim)
	-- Get our pieces
	tell aDate to set {yr, mo, dy, hr, mn, sc} to {its year, its month as number, its day, its hours, its minutes, its seconds} -- AppleScript understands assigning values to list items, and "telling" aDate enables us to use "its" in place of "of aDate" in every entry.
	-- Build our stamp
	set TS to "" -- initialize our output string to an empty string
	--return {yr, mo, dy, hr, mn, sc} -- uncomment to see the values of the parts
	repeat with D in {yr, mo, dy, hr, mn, sc} -- adjust each of the parts to be two characters
		if length of ((contents of D) as text) < 2 then set contents of D to "0" & D -- stick a "0" in front of single.
		set TS to TS & D & aDelim -- add this piece to the rest (called concatination)
	end repeat
	return characters 3 thru -2 of TS as string -- skip the "20", and the final "aDelim character".
end makeTimeStamp

i’m thinking of making a small change to the existing application.

i now have a text file with “jobs” and “data path”
example:

10110 SERV:PROJECTS:10110:DATA:
10111 SERV:PROJECTS:10111:SAMPLE:REC:

…And so on

So, Instead of asking the the user to browse and choose the resource folder after getting the “Job Number” i need to read through the file and find the job number and the related path and then assign the path to f3

Is this possible?

The short answer is probably.

The long answer requires much more information.

“… after getting the “Job Number” i need to read through the file and find the job number …” doesn’t make sense. Given a job number find the job number.

“… assign the path to f3 …” What’s f3? a variable, an FKey? If a key you should know that AppleScript by itself cannot assign a key to a script. There are other tools that will like QuicKeys or FastScripts.

“… need to read through the file …” What file? The path file? Do you mean given 10110 find 10111?

Sorry Guys,

  The last post was realllly bad.. Maybe i needed some coffee/good sleep. Ayways what i was trying to do is this
  1. Have A tab delimited text file in the server where i keep data about job locations (Paths)

The text file is like this
JA1564 SERV:Projects:JA1564 Rubber:Original:
OM1747 SERV:Projects:OM1747 Sheets:Downloads:

Now i want my script to do the following

  1. Ask user to input jobno
  2. Search this textfile(i’d hardcore the text file’s location)and get the path for the job
  3. Copy all the files from that folder and save in local work folder (hardcoded too)
  4. Simultaneously take a backup of local work folder into a new folder(with date and time as foldername)
  5. Exit

Here’s wht i came up with so far


-- Function To generate sytem date and time
to makeStamp(Now, delim)
	set d to "-" -- Delimiter between the numbers
	tell Now to tell 100000000 + day * 1000000 + (its month) * 10000 + year as string to set dateStamp to text -2 thru -1 & d & text 4 thru 5 & d & text 2 thru 3
	tell Now to tell ((10000 + (its hours) * 100 + (its minutes)) as string) to set timeStamp to text 2 thru 3 & d & text 4 thru 5
	tell Now to tell ((its seconds) as string) to set sec to text -2 thru -1
	return dateStamp & d & timeStamp & d & sec
end makeStamp

--App Begins  
on run
	---------------Path Check----------------
	set filepath to "SERV:PROJECTS:SCRIPTS:"
	set fname to "Jpath.txt"
	--set myFile to (choose file)
	set myFile to filepath & fname as alias
	set myText to read myFile
	
	set myLines to paragraphs 2 thru -1 of myText
	
	set mySearch to text returned of (display dialog "Enter 5-Digit Project Code:" default answer "")
	
	--set mytab to "Invalid project code or file information not available."
	try
		repeat with myLine in myLines
			
			if myLine contains mySearch then
				set AppleScript's text item delimiters to {tab}
				set mytab to get second text item of myLine
				
				exit repeat
			else
				--display dialog "Invalid Code" buttons {"Ok"}
				--exit repeat
				--continue quit
			end if
			
		end repeat
	on error
		display dialog "Invalid Code"
	end try
	--display dialog mytab
	
	
	-------------End Of Path Check-----------
	-----Initialize Local Disk----	
	tell application "Finder"
		get name of startup disk
		set thisdisk to name of startup disk
		set mydisk to thisdisk & ":"
		--display dialog mydisk
	end tell
	-----End Initialization-------
	
	set Now to (current date)
	set myFolder to makeStamp(Now, ".") 
	
	--Creating a folder in the date's name
	tell application "Finder"
		try
			set targetfolderpath to mydisk & "filesBackup:"
			set newfoldername to myFolder
			if folder (targetfolderpath & ":" & newfoldername) exists then
			else
				make new folder in folder targetfolderpath with properties {name:newfoldername}
			end if
		end try
	end tell
	--display dialog myFolder
	--Set path for backup and transfer folders	
	set folder_path to mydisk & "Work Folder:Data:"
	set backup_path to mydisk & "Data Backup:" & myFolder & ":"
	
	try
		tell application "Finder" to move every file of folder folder_path to backup_path
		
	on error
		display dialog "Cannot Move Files! Quit All Applications"
	end try
	tell application "Finder"
		activate
		
		-----BLOCK CHECKS AND DISPLAYS NOT FOUND MSG
		try
			set f3 to mytab
		on error
			display dialog "Project Not Found" buttons {"Ok"}
		end try
		-----------		
		tell application "Finder" to delete every file of folder folder_path
		
		
		tell application "Finder"
			try
				copy every file of folder f3 to folder folder_path
				display dialog "Files Loaded" buttons {"OK"}
			end try
		end tell
	end tell
	----------------	
end run

:frowning:
Ok i know this scrpt if fulla holes :rolleyes: . Atleast it does a few things. It reads the file and if the path is found it copies all the files from that location. But for some reason if i give a wrong input it does not give me a error message. i wanted the script to quit if the wrong project no is given but it isnt happening.

it’d be really helpful if someone can help me with this. And i’m really sorry about the last post

If you really want seconds in your time stamp, use this. The way you had it it failed if the “seconds” was a single digit.

to makeStamp(Now, delim)
	set d to delim -- Delimiter between the numbers
	tell Now to tell 100000000 + day * 1000000 + (its month) * 10000 + year as string to set dateStamp to text -2 thru -1 & d & text 4 thru 5 & d & text 2 thru 3
	tell Now to tell (((1000000 + (its hours) * 10000 + (its minutes) * 100) + (its seconds)) as string) to set timeStamp to text 2 thru 3 & d & text 4 thru 5 & d & text 6 thru 7
	return dateStamp & d & timeStamp
end makeStamp

set Now to (current date)
set myFolder to makeStamp(Now, "-")

Try this:

---------------Path Check----------------
set filepath to "SERV:PROJECTS:SCRIPTS:"
set fname to "Jpath.txt"
--set myFile to (choose file)
set myFile to filepath & fname as alias
set myText to read myFile
set mySearch to text returned of (display dialog "Enter 5-Digit Project Code:" default answer "")
if myText contains mySearch then
	repeat with P in paragraphs 2 thru -1 of myText
		if P contains mySearch then
			set AppleScript's text item delimiters to {tab}
			set mytab to second text item of P
			set AppleScript's text item delimiters to ""
			-- always set them back or on your next run it'll screw up
			exit repeat
		end if
	end repeat
else
	display dialog "Project Code Submitted Not Found"
end if
mytab
-------------End Of Path Check-----------

If I had a better idea of what the document being read contained, we could probably do this without the loop as in this example.

set f to alias "theFilePath"
set tf to read f
set delim to "J4 : "
if tf contains delim then
	set text item delimiters to delim
	set j to last text item of tf
	set text item delimiters to "MB"
	set m to last word of first text item of j & "MB"
	set text item delimiters to ""
else
	display dialog "It ain't there"
end if
m --> "128MB"

(* The text in my file

J3 : DIMM configured for 32MB
10.0 ns PC66-222
SPD data revision is old or incorrect
DIMM checks out OK

J4 : DIMM configured for 128MB
8.0 ns PC100-322
Checksum is incorrect
DIMM checks out OK

J5 : DIMM configured for 256MB
7.5 ns PC122-333
Note: the number of column address bits
      is not compatible with newer Macs
DIMM checks out OK

*)

i’m sorry i was not clear about that. The text document has 2 elements jobno and the path for the job’s resource(documents, fonts, excel sheets etc)

it looks like this

A1564 SERV:Projects:JA1564 Rubber:Original:
OM174 SERV:Projects:OM1747 Sheets:Downloads:

Where A1564 is the job no And SERV:Projects:JA1564 Rubber:Original: is the path where the job related files are stored the document may contain anywhere between 50 - 200 such rows. And if a job number is entered by the user its searched within the document and the path for that is retrieved.

My current script looks like this

----------Folder Creation-------------
to makeStamp(Now, delim)
	set d to delim -- Delimiter between the numbers
	tell Now to tell 100000000 + day * 1000000 + (its month) * 10000 + year as string to set dateStamp to text -2 thru -1 & d & text 4 thru 5 & d & text 2 thru 3
	tell Now to tell (((1000000 + (its hours) * 10000 + (its minutes) * 100) + (its seconds)) as string) to set timeStamp to text 2 thru 3 & d & text 4 thru 5 & d & text 6 thru 7
	return dateStamp & d & timeStamp
end makeStamp

--set Now to (current date)
--set myFolder to makeStamp(Now, "-")

----------Finding file Path-----------
on run
	set filepath to "SERV:PROJECTS:PATH:"
	set fname to "file.txt"
	--set myFile to (choose file)
	set myFile to filepath & fname as alias
	set myText to read myFile
	set mySearch to text returned of (display dialog "Enter 5-Digit Project Code:" default answer "")
	if myText contains mySearch then
		repeat with P in paragraphs 2 thru -1 of myText
			if P contains mySearch then
				set AppleScript's text item delimiters to {tab}
				set mytab to second text item of P
				set AppleScript's text item delimiters to ""
				-- always set them back or on your next run it'll screw up
				exit repeat
			end if
		end repeat
	else
		display dialog "Project Code Not Found"
	end if
	try
		mytab
	on error
		continue quit
	end try
	--------------Initialize Disk----
	if mytab is "" then
		continue quit
	else
		tell application "Finder"
			get name of startup disk
			set thisdisk to name of startup disk
			set mydisk to thisdisk & ":"
			--display dialog mydisk
		end tell
		-----End Initialization-------
		----Create Folder With Date Hour Minute and Seconds-----
		set Now to (current date)
		set myFolder to makeStamp(Now, ".")
		
		
		tell application "Finder"
			try
				set targetfolderpath to mydisk & "filesBackup:"
				set newfoldername to myFolder
				if folder (targetfolderpath & ":" & newfoldername) exists then
				else
					make new folder in folder targetfolderpath with properties {name:newfoldername}
				end if
			end try
		end tell
		
		--Set path for backup and transfer folders	
		set folder_path to mydisk & "System Folder:files:"
		set backup_path to mydisk & "filesBackup:" & myFolder & ":"
		
		--	visual confirmation display dialog backup_path
		try
			--display dialog "Are you sure you want to move all the files from System Folder:files?"
			tell application "Finder" to move every file of folder folder_path to backup_path
			
		on error
			display dialog "Cannot Move files! Quit All Applications"
		end try
		tell application "Finder"
			activate
			
			--------Mess Clear it up later		
			
			-----BLOCK CHECKS AND DISPLAYS NOT FOUND MSG
			try
				set f3 to mytab
			on error
				display dialog "Project Not Found" buttons {"Ok"}
			end try
			-----------		
			tell application "Finder" to delete every file of folder folder_path
			
			tell application "Finder"
				try
					copy every file of folder f3 to folder folder_path
					display dialog "files Loaded" buttons {"OK"}
				end try
			end tell
		end tell
	end if
	----------------	
end run

When i run the script from the script editor and i enter an invalid job no then it shows the message “Not found”, and says veriable mytab not set and quits. whereas if i save it as an application and then run it, it shows the not found error and still continues to proceed with the rest of the script.

I am not able to figure out what the issue might be.

PS: i hope i have posted a better description this time:)

  1. If you’re getting serious about distributing this to others, then it needs some error checking.
  2. If the text file always looks like your example, then the following avoids running through a loop to look at the text line-by-line by using text item delimiters.
--set filepath to "SERV:PROJECTS:PATH:"
--set fname to "file.txt"
--set myFile to filepath & fname as alias
set myText to read myFile
set valid to {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
repeat
	set mySearch to text returned of (display dialog "Enter 5-Digit Project Code:" default answer "")
	-- check for valid entry -- a letter followed by four numbers
	if length of mySearch = 5 then
		set chk to text items of mySearch
	else
		display dialog "The Project Code must have one capital letter and four numbers."
	end if
	considering case
		if item 1 of chk is in valid then
			try
				set nums to rest of chk as string as number
				exit repeat -- everything checked so press on
			on error e
				display dialog "The Project Code must end in four numbers"
			end try
		else
			display dialog "The first character of the project code must be a capital letter"
		end if
	end considering
end repeat

if myText contains mySearch then
	set astid to AppleScript's text item delimiters -- get current setting
	set AppleScript's text item delimiters to mySearch & tab -- split the file at job#
	set lti to last text item of myText -- starting just after the tab following job#
	set AppleScript's text item delimiters to astid -- restore delimiters
	set mytab to first paragraph of lti -- the path
else
	display dialog "Project Code Not Found"
	-- quit can be included if script is saved as an application -- otherwise you're telling the script editor to quit.
end if

Thanks for the help Adam Bell

One thing bothers me though. As you had mentioned i saved the script as an application and included the “Continue Quit” bit and this is what happened

  1. I ran the application and entered a valid project number, here it searched the path and copied the resource files correctly.

  2. I ran the app again and entered an invalid job number. It displayed the error message “Project Not Found” and still continued to the rest of the code. In fact it performed the last copy operation(the one that it performed for the valid jobnumber) again.

Are you saying that this doesn’t work?

display dialog "Project Code Not Found"
quit

That line is being executed and the program does not execute “Continue Quit” it progresses and performs the last copy operation. This happens only if i save it as an application.

In your original, you had this:

...
 else
       display dialog "Project Code Not Found"
   end if
   try
       mytab
   on error
       continue quit
   end try

I’m asking, did you try this:

 ...
else
display dialog "Project Code Not Found"
quit

without the try block you have following it.

Oh. Sorry. I tried it and it worked. Thanks for your help Adam Bell

Edit: I’ve run into another problem. I am trying to run the application on different machines. When i run the application in the certain machines i get this error message

Cant get hours of date “Monday, July 31, 2006 5:07:31 PM”

This is how i tested

Machine 1: OSX Version 10.4.2 (iMac) - Worked Well
Machine 2: OSX Version 10.4.7 (PowerPC G5) - Worked Well
Machine 3: OSX Version 10.3.4 (PowerPC G5) - Failed
Machine 4: OSX Version 10.3.4 (eMac) - Failed

Can someone tell me what’s wrong?