http download & replace file in user preferences script help needed

I am a learning novice, so please be patient with me. I do not know terminal/unix commands, etc. despite using macs for 18 yrs. :smiley:

Objective: download a text-like file from a web page, replace the older equivalent file in a user’s program preference folder.
Steps:
1. Download file.
2. Replace the older file. Ideally (1) & (2) would happen simultaneously but I’ve not been able to achieve this. (eg: download & replace.)
3. Chronologically, this would occur first: Check to be sure the older file is not busy.

I suspect an experienced scripter would take about 3 minutes to write the above script.
I seem to be having problem getting the file to move & replace the older file. Not sure the script can even find the folder. I’ve tried almost 20 ways of achieving this. Presently the download command simply downloads the file to the root of the startup drive (/).

This part works alone but downloads to root:

try
	display dialog ("LimeWire must be closed before running this Fix program")
	set newFile to ("gnutella.net")
	tell application "URL Access Scripting"
		activate
		download "http://dl.frostwire.com/frostwire/gnutella.net" to newFile with progress
		display dialog ("Fix finished. ...")
		quit
	end tell
end try

Original attempts to download directly to the location failed:

try
	display dialog ("LimeWire must be closed before running this Fix program")
	set newFile to ("gnutella.net")
	set theDestinationPath to "~/preferences/LimeWire/"
	tell application "URL Access Scripting"
		activate
		download "http://dl.frostwire.com/frostwire/gnutella.net" to "~/Preferences/LimeWire/gnutella.net" with progress and replacing
		display dialog ("Finished, now ...")
		quit
	end tell
end try

Attempts to move the file have failed. Below is simply an example of my last attempt:

try
	display dialog ("LimeWire must be closed before running this Fix program")
	set newFile to ("gnutella.net")
	tell application "URL Access Scripting"
		activate
		download "http://dl.frostwire.com/frostwire/gnutella.net" to newFile with progress
		
		set theSourcePath to newFile
		set theDestinationPath to "~/preferences/limewire/"
		tell application "Finder"
			move newFile to theDestinationPath with replacing
			display dialog ("Finished, now ..")
			quit
		end tell
	end tell
end try

This script combining downloading & checking if file to be replaced is busy does not appear to work at all, I guess the isBusy part is incorrect:

to isBusy(f)
	set f to f as Unicode text
	display dialog ("LimeWire must be closed before running this Fix program")
	if f does not contain ":" then set f to POSIX file f as Unicode text
	try
		open for access file (system attribute "HOME") & ("~preferences/LimeWire/gnutella.net") with write permission
		close access result
		return false
		if false then
			set newFile to ("gnutella.net")
			tell application "URL Access Scripting"
				activate
				download "http://dl.frostwire.com/frostwire/gnutella.net" to newFile with progress
				display dialog ("Fix finished. 
		
		Now open LimeWire and see if it connects.
		Wait 3-4 minutes for it to connect. 
		
		If no connection, CLOSE LimeWire.
		Wait another 2 minutes, then run this script again.")
			end tell
		else
			return true
			display dialog ("LimeWire settings are still active, close this fix program and wait a minute before trying again")
		end if
		
	on error
		display dialog ("LimeWire settings are still active or you do not have an active internet connection, close this fix program and wait a minute before trying again")
		quit
	end try
end isBusy

Side questions: From my understanding, if this script were offered as a program, it would only be compatible with OSX 10.5 & above?
If I wished to recreate equivalent for OSX 10.4 down to OS9, would this be possible & which version of Applescript? I still have G4 with OSX 10.4 & 10.3 (with Classic.)
I am more used to using VISE which is very easy for it’s basic functions, but unfortunately does not support actively updating installers such as this project (I had wondered if one could be combined with applescript.)

Model: 2x3.2 Quad Core, OSX 10.6.8
AppleScript: AppleScript 2.1.2, A.Editor 2.3
Operating System: Mac OS X (10.6)
Edit: Removed some unnecessary script dialog to save space in post.

OS X is a Unix OS with graphical API/Layer above it which presents Mac OS X. OS 9 and earlier is a complete different system which was an complete Macintosh System. In Mac OS you had scriptable extensions while URL Access scripting is in OS X an scriptable application. So the code for OS 9 is different than the code for OS X (using url access scripting or do shell script with curl) which means you’ll need a pre-loader. The preloader needs to determine with OS independed code which script to load and run.

Both systems can work with the Finder and both can call the Finder version, the version equals the installed OS.

to determine which script to call:


if version of application "Finder" starts with "10." then
set theScript to load script file "OSXDownloader.scpt" --macintosh path to script
else
set theScript to load script file "MACOSDownloader.scpt" --macintosh path to script
end if
run theScript

Thank you for the very helpful & speedy reply. I had not considered a pre-loader. Sounds logical. :slight_smile:

Perhaps I missed marking the point.

Would it be possible for anybody to explain what I’ve done wrong in my script code?

How to download directly & replace within a user’s program preferences folder?
Else, how to move from root to a specific user’s program preference folder?
(seems my script cannot even find the folder … I’ve attempted different techniques after googling different code techniques.)

http download does not appear to be a well documented feature either in manuals or on forums. Nor is the concept of applescript finding things within a user’s preferences folder. I’m sure the Finder can find it … else why is it called Finder? lol Something’s wrong with my attempts how to tell Finder how to find the folder in question. I could quote about 15 ways I found, all have failed.

The above is the first priority, obviously, else the script is fruitless.

You’l notice i registered on the 22 August, 2-3 days after I initially wanted to post here. I delayed posting, instead attemping all I could find. I feel I’m lost for alternatives.

A simple command can do the download on OS X very simple


do shell script "curl -s 'http://www.myserver.com/downloads/myfile.plist' > /Users/<shortname>/Library/preferences/myfile.plist"

A simple, one line to download a file. But I didn’t think this would be your problem because for me making a script for OS 9 till today’s version would be the great challenge and not the part for downloading a file.

As for checking if a file is busy, use the busy status property of info for.

busy status of (info for file "filePath")

Thank you both for your very helpful replies. :slight_smile:

do shell script "curl -s 'http://www.myserver.com/downloads/myfile.plist' > /Users/<shortname>/Library/preferences/limewire/gnutella.net"

Script could not find location. It exists in 4 accounts on the computer & in a secondary startup drive. lol

At least for time being, I’ve sufficed with a compromise. Combined VISE with the original http applescript. Although vise supports applescript & Unix, I had issues adding so I did it other way around & put the vise app into the script program bundle. It is a very sloppy approach but seems to work for now. lol Until I learn more about applescripting. That could take quite some time I think. :frowning:

You have to change the URL and path to an existing path and URL. http://www.myserver.com/downloads/myfile.plist’ was just an example of what you should use and I don’t know the real URL so change that to the real download URL. Also I posted in the path but of course this needs to be replaced with the shortname of the current user. Like


set theTargetFile to quoted form of POSIX path of ((path to library folder from user domain as string) & "Preferences:limewire:gnutella.net")

Now the variable theTargetFile contains a path to the gnutella file now matter which user is logged in.

Thank you :smiley: Finally the shell script works for me lol No idea if what I did is totally correct but seems to work. :lol:

set theTargetFilename to ("gnutella.net")
set theTargetFile to quoted form of POSIX path of ((path to library folder from user domain as string) & "Preferences:limewire:gnutella.net")
do shell script "curl -s 'http://dl.frostwire.com/frostwire/gnutella.net' > ~/Library/preferences/limewire/gnutella.net"

When running the script says the result is ā€œā€ I presume that is correct.
This works faster than the standard applescript. I’ll look into the Busy mode testing.

Oops found a bug with the script.
The file to download should be 8 KB in size & have about 199 lines of text (ip addresses.)
The shell script however is only creating a 4 KB file with 50 lines. Would the unix command be finishing before it has properly written or downloaded the entire contents of the file from the website? Any fix for this?
My earlier work using the applescript http command results in an appropriate size file.

Strange, sometimes writes a 8 KB file with around 200 lines, sometimes 4 KB with only 50 lines. About first 20 tests in different computer accounts ended up with 4 KB file. Tests since seem to be good at least for now.
Any way of guaranteeing a 8 KB file with 200 lines?
Such as checking the file after writing & if less than 150 lines to repeat download process?

You’ll only need to line:

do shell script "curl 'http://dl.frostwire.com/frostwire/gnutella.net' > ~/Library/preferences/limewire/gnutella.net"

The rest is unused code.

But I’m not sure this is the problem. I would say the error is on the server side. When I dump the header of the download to an file like this


set HTTPUserAgent to "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:6.0.1) Gecko/20100101 Firefox/6.0.1"
do shell script "curl --user-agent " & quoted form of HTTPUserAgent & " --head 'http://dl.frostwire.com/frostwire/gnutella.net'"

[START EDIT]I simplified the code above [END EDIT]

I added a user agent so the server thinks that the latest firefox is been used to download the file.

You can see that the server returns the content length every time differently. Also it says that the content type is an application/octet-stream while this isn’t true. But this shouldn’t be a problem normally.

Thanks for the test. I believe the file is sent from more than one copy on their network, thus depending on occasion you end up with a different copy with totally different data. With just manual browser downloading I’d noticed once in a while getting a 4 KB file, but to initially get it so frequently with the script was worrying. The file needs to be at least 100 lines long for it to be useful.

Apologies if I’ve been a little persistent in my questions. :smiley:
With a script to check file-size I can then potentially loop back to the download script if the file-size is not larger than certain size. However, I’ve forever had a problem actually correctly specifying the correct location for Finder to find the file in question. (Always says cannot find, even if the error message specifies the path exactly.)
Below is a test with a gnutella.net file on the desktop. But how can I specify the location of /users/username/library/preferences/limewire/gnutella.net ?

tell application "Finder"
	set x to ":Users:username:Desktop:gnutella.net" as alias
	repeat
		try
			set y to physical size of item x as integer
			exit repeat
		on error
			delay 1
		end try
	end repeat
	if y is greater than 5000 then
		display dialog ("FINISHED") --ie: 8000 being correct size, anything below 5000 (5 KB) probably being a dud download of the file.
	else
		display dialog ("oops") -- this part would loop back to the shell script to try again.
	end if
end tell

Another method is counting the lines in the file with this. It keeps downloading until it has more than 190 lines…

set linesInFile to 0
repeat until linesInFile > 190
	set linesInFile to (do shell script "curl 'http://dl.frostwire.com/frostwire/gnutella.net' > ~/Library/preferences/limewire/gnutella.net; cat ~/Library/preferences/limewire/gnutella.net | wc -l") as integer
end repeat

Thank you, works like a charm. :slight_smile: I had spent hours working on getting a document line-count script working using various ways but gave up. lol My concern with the file-size check was with the earlier OSX’s using a different manner of specifying file-size (they would show as being smaller I guess. Unless the particular OSX responded to the applescript command with the identical file-size protocol.)

For the future, how could I specify a user’s LimeWire preference folder item using applescript? Reason I ask is I had considered a backup script for one or two files in the folder (that may once in a while become corrupted.)
Am I better to learn shell commands instead? :smiley: I did bookmark an osx shell command page but then I need to learn how to use.
Applescript recording gives a command like:

set target of Finder window 1 to folder "LimeWire" of folder "Preferences" of folder "Library" of folder "(me)" of folder "Users" of startup disk"

but I need to find a generic command reference that will refer to the active username’s preferences folder of any computer.

set target of Finder window 1 to folder "LimeWire" of folder "Preferences" of folder "Library" of folder home

does not work.
ā€œFinder got an error: Can’t set Finder window 1 to folder "LimeWire" of folder "Preferences" of folder "Library" of folder (folder "me" of folder "Users" of startup disk).ā€ number -10006 from Finder window 1

The reason I use shell script a lot is that they have utilities who can handle data much faster and much better. Another reason is that most services runs in the shell (runs below Mac OS X layer) and can therefore work perfectly with other shell commands and piping data from one process to another is quite handy then. The difference between AppleScript and the shell is that the next example is a table in the shell while it is a string for AppleScript.

1 field value 1 field value 2 field value 3
2 field value 4 field value 5 field value 6
3 field value 7 field value 8 field value 9

For you path question there are first of all several domains in your system. User domain, system domain, local domain, network domain and classic domain. If you’re not a network user the last two are not important. You can tell ā€˜path to’ command in which domain it searches. The path to command gives you a path to a folder you pass as an argument (see standard addition documentation for all possible values).

Some commands

path to library folder 
path to library folder from user domain
path to library folder from system domain
path to preferences folder
path to preferences folder from local domain
path to preferences folder from system domain--results in an error

As you can see that preferences folder and library folder have both a different default domain. Path to library is default in the local domain while preferences is default in the user domain. So if you’re not sure you can use domain to make it sure you ask the folder in the right domain. If you ask for a path that doesn’t exists in that domain , you’ll get an error, like in the last command with tring to get preferences folder of system domain.

to complete your path to the gnutella.net path you need to append a string to it. You also need the parentheses around path to command so the concatenation of strings will succeed.

(path to preferences folder from user domain) & "limewire:gnutella.net" as text

Many thanks for your earlier assistance. I have a further question on this topic.

I have created an almost identical script for another similar program despite the file is sent to application support folder instead. However what I wish to do is insert 10 lines of text at the beginning of the file after unix writes the gnutella.net file. How can I achieve this?

Say for example I wished to insert:

hello.sgt.net:029283,4232,
blahblah.xt.org:42049,
etc. …