The macosxhints Forums

The macosxhints Forums (http://hintsforums.macworld.com/index.php)
-   OS X Developer (http://hintsforums.macworld.com/forumdisplay.php?f=27)
-   -   How to find out if file exists in /tmp folder with Apple script (http://hintsforums.macworld.com/showthread.php?t=90226)

Nata 05-30-2008 04:31 PM

How to find out if file exists in /tmp folder with Apple script
 
I have a trouble about understanding how to create correctly the name of the file to ask "Finder" if such file exists. Especially I need to find file in /tmp folder.
This is what I tried to do:
tell application "Finder"
set myfile to "/tmp/my_file" as alias
set thereis to exists file myfile
end tell

hayne 05-30-2008 04:51 PM

You need to use 'POSIX file' if you are giving Unix-style paths.

set myfile to POSIX file "/tmp/my_file" as alias

tw 05-30-2008 06:18 PM

you can either use

set myfile to POSIX file "/tmp/my_file"

as hayne suggested, or translate it into Mac-ese yourself

set myfile to "HD:tmp:my_file" as alias

cwtnospam 05-30-2008 08:48 PM

FYI,
I don't know about Leopard, but in Tiger's Script Editor, using
set myfile to POSIX file "/tmp/my_file" as alias
results in
set myfile to "HD:tmp:my_file" as alias
as soon as you save the script.

tw 05-30-2008 08:52 PM

Quote:

Originally Posted by cwtnospam (Post 473333)
FYI,
I don't know about Leopard, but in Tiger's Script Editor, using
set myfile to POSIX file "/tmp/my_file" as alias
results in
set myfile to "HD:tmp:my_file" as alias
as soon as you save the script.

yeah, the POSIX file thing is really intended to be used with variables, not hard-coded paths. buhwaddayagunnadoo...

cwtnospam 05-30-2008 08:54 PM

I'm curious about how Leopard handles it because it's supposed to be fully POSIX. Does it stay as a POSIX path?

tw 05-30-2008 09:26 PM

in Leopard (10.5.3), it seems to stay as POSIX file "/tmp" in the text, though the result it returns is file "HD:private:tmp". that might be a 10.5.3 change, though, because I seem to remember it not doing that previously.

Mikey-San 05-30-2008 09:28 PM

That Script Editor does or doesn't do path conversion has nothing to do with Mac OS X's POSIX compliance. It's simply a behaviour of the Script Editor compile-time parser. To answer your question, though, the Leopard Script Editor doesn't change it to an alias path. I don't have a Tiger machine handy to duplicate the behaviour you're seeing, unfortunately.

Quote:

yeah, the POSIX file thing is really intended to be used with variables, not hard-coded paths.
That is not true. Here's an example of Apple using a hard-coded path to /tmp:

http://developer.apple.com/documenta...0983-CH1g-SW15

Mikey-San 05-30-2008 09:29 PM

Quote:

Originally Posted by tw (Post 473339)
in Leopard (10.5.3), it seems to stay as POSIX file "/tmp" in the text, though the result it returns is file "HD:private:tmp". that might be a 10.5.3 change, though, because I seem to remember it not doing that previously.

Ah, an interesting find. Perhaps there's some kind of conversion going on back and forth in the AS runtime.

tw 05-30-2008 09:41 PM

Quote:

Originally Posted by Mikey-San (Post 473340)
That is not true. Here's an example of Apple using a hard-coded path to /tmp:

http://developer.apple.com/documenta...0983-CH1g-SW15

I beg to differ: from that very page:
Quote:

POSIX file
A pseudo-class equivalent to the file class.

There is never an object whose class is POSIX file; the result of evaluating a POSIX file specifier is a file object. The difference between file and POSIX file objects is in how they interpret name specifiers: a POSIX file object interprets "name" as a POSIX path, while a file object interprets it as an HFS path.
in other words, the POSIX file class is little more than an explicit coercion to the standard File class.

tw 05-30-2008 09:45 PM

Mikey - thanks for that link, by the way. I hadn't realized there was a newish versions of the ASLG out.

Mikey-San 05-30-2008 10:09 PM

Quote:

Originally Posted by tw (Post 473342)
I beg to differ: from that very page:


in other words, the POSIX file class is little more than an explicit coercion to the standard File class.

That still does not say or imply that it's meant for use only with variables.

Edit: The point being that Apple doesn't say one way or another if you should or shouldn't use absolute, hard-coded paths with "POSIX file". In general, regardless of POSIX file, you should be wary of using absolute, hard-coded paths to file system locations for a multitude of reasons.

Mikey-San 05-30-2008 10:14 PM

I am now curious:

What is your intent of testing if a file exists in /tmp? I bet if you elaborated a bit, you'd gain additional insight from the crew here.

tw 05-30-2008 10:16 PM

Quote:

Originally Posted by Mikey-San (Post 473344)
That still does not say or imply that it's meant for use only with variables.

Edit: The point being that Apple doesn't say one way or another if you should or shouldn't use absolute, hard-coded paths with "POSIX file". In general, regardless of POSIX file, you should be wary of using absolute, hard-coded paths to file system locations for a multitude of reasons.

true, and true. I guess I was just interpolating. my bad. :)

Mikey-San 05-30-2008 10:18 PM

I would also recommend not using the Finder if at all possible. The less you tell the Finder to do, the better you and your users will be overall. Remember, the Finder is one of the most-used applications, and AppleScript commands run on the main thread. Your script may have to wait on the Finder to complete some other task, or the script may block another task until it finishes. This stuff adds up!

How often do you need to test for the existence of this file? What else are you doing before and after it?

Mikey-San 05-30-2008 10:19 PM

And ONE LAST QUESTION I SWEAR:

Is this vanilla AppleScript, or AppleScript Studio? If it's Studio, we can show you even more ways of doing whatever it is your goal happens to be. :)

Mikey-San 05-30-2008 10:22 PM

Quote:

Originally Posted by tw (Post 473343)
Mikey - thanks for that link, by the way. I hadn't realized there was a newish versions of the ASLG out.

Yeah, they updated AppleScript heavily in Leopard, leading to a big documentation update. It was long overdue.

Check out this release note:

http://developer.apple.com/releaseno...ipt/index.html

cwtnospam 05-31-2008 12:16 PM

Quote:

Originally Posted by Mikey-San (Post 473347)
I would also recommend not using the Finder if at all possible. The less you tell the Finder to do, the better you and your users will be overall.

With this in mind, it seems better to use a shell script:

Code:

set filename to "My_filename.*"
set command to "ls /tmp/" & filename
set x to do shell script command

If x = "" then the file does not exist!

Mikey-San 05-31-2008 12:58 PM

Quote:

Originally Posted by cwtnospam (Post 473441)
With this in mind, it seems better to use a shell script:

Code:

set filename to "My_filename.*"
set command to "ls /tmp/" & filename
set x to do shell script command

If x = "" then the file does not exist!

I prefer:

Code:

on fileExistsAtPath(path)
        local fileExists -- boolean
       
        try
                set result to (do shell script "if [ -f " & quoted form of path & " ] ; then exit 0 ; else exit 1 ; fi")
                set fileExists to true
        on error theError
                set fileExists to false
        end try
       
        return fileExists
end fileExistsAtPath

Here's a raw performance comparison between this function and using the Finder while completely idle:

Code:

property testFile : "/Users/mikey/Desktop/some file.txt" -- a file we want to test for existence
property testCount : 1000 -- how many times we want to look for the file, for performance comparison (mikey's fileExistsAtPath() vs finder)

on run
        local startTime -- integer - the time from the epoch in seconds when we started timing a sequence
        local endTime -- integer - the time from the epoch in seconds when we ended timing a sequence
        local timeDiff -- integer - the number of seconds a sequence took to execute
       
        set startTime to (do shell script "date +%s") as integer
        repeat testCount times
                fileExistsAtPath(testFile)
        end repeat
        set endTime to (do shell script "date +%s") as integer
        set timeDiff to (endTime - startTime)
       
        display dialog (testCount as string) & " loops of mikey's fileExistsAtPath() took " & timeDiff & " seconds."
       
        set startTime to (do shell script "date +%s") as integer
        repeat testCount times
                tell application "Finder"
                        exists testFile as POSIX file
                end tell
        end repeat
        set endTime to (do shell script "date +%s") as integer
        set timeDiff to (endTime - startTime)
       
        display dialog (testCount as string) & " loops of 'tell finder exists' took " & timeDiff & " seconds."
end run

on fileExistsAtPath(path)
        local fileExists -- boolean
       
        try
                set result to (do shell script "if [ -f " & quoted form of path & " ] ; then exit 0 ; else exit 1 ; fi")
                set fileExists to true
        on error theError
                set fileExists to false
        end try
       
        return fileExists
end fileExistsAtPath

On my MacBook Pro, the average of three runs was 7 seconds with fileExistsAtPath() vs 18 seconds with Finder. YMMV. The other benefit, of course, is that you aren't tying up the Finder during the operation (or aren't waiting on the Finder while it does other stuff).

I would prefer using the shell's -f test over spawning both a shell process and an ls process. An exercise for the reader would be to modify my function to use ls instead of -f and see what the performance difference is with 1000 tests.

Edit:

I've got an additional reader exercise that would be a good one for anyone who wants to learn more about AppleScript (and programming in general). Modify the fileExistsAtPath() function to tell you both if the path exists and if the path is a directory or not, without altering the return value.

cwtnospam 05-31-2008 01:54 PM

Quote:

Originally Posted by Mikey-San (Post 473455)
I would prefer using the shell's -f test over spawning both a shell process and an ls process. An exercise for the reader would be to modify my function to use ls instead of -f and see what the performance difference is with 1000 tests.

My feeling was that the ls process would be faster than the extra Applescript code. If some one does the exercise, I'd be interested in the results. ;)

Nata 05-31-2008 01:56 PM

Thank a lot
 
Your recommendations are very useful. Well, finding out existence of this script is a workaround to find out if app runs.
Firstly, I wrote a shell script where called osascript $COMMAND (where $COMMAND is apple script command). But this shell script is running from some app and performed under root (I can't change this).
And on Leopard (and maybe on Tiger) osascript is not performed under root.
So I tried to call from shell script "osasscript myscript.scpt".
Seems that in this case myscript.scpt is not performed under root.
But I need to know if app (for example "Address Book" is not running).
For some reasons some commands "do shell script " (like sed -n '$=' file_name) in myscript.scpt does not work on Leopard either. It does not mean that they don't work if I run it right from Terminal, but only when I run it from my app. So I'm trying to find some other ways to solve my problem.
Maybe it would be easier to get out if app is not active? But I'm newcomer about apple script, and need to solve this problem as quickly as can.

Mikey-San 05-31-2008 02:08 PM

Why go by feeling when you can test it? Performance can always be analyzed; don't make implementation decisions based on assumptions of performance. ;)

I also prefer -f because it's more explicit. You want to know if a file exists, and there is a reasonably fast way of doing it explicitly. No reason to spawn two processes instead of one, when one is the explicit version that is already fast.

For what it's worth, if you use ls and the file doesn't exist, ls exits non-zero, which causes "do shell script" to throw an error that has to be caught with try/on error anyway. You don't really save any code.

Mikey-San 05-31-2008 02:12 PM

Quote:

Well, finding out existence of this script is a workaround to find out if app runs.
You should've told us your actual goal in your very first post, because the answer is completely different. I have to run out for the afternoon, so I can't address it, but I imagine someone will come along shortly and do so.

cwtnospam 05-31-2008 02:18 PM

Quote:

Originally Posted by Mikey-San (Post 473476)
For what it's worth, if you use ls and the file doesn't exist, ls exits non-zero, which causes "do shell script" to throw an error that has to be caught with try/on error anyway. You don't really save any code.

I had thought that would be the case, but I was working on my wife's computer, which is running 10.3.9, and it worked as I have it listed, whether or not the file existed. Trying the same code on my machine running Tiger does throw an error, so I guess the point is moot.

cwtnospam 05-31-2008 02:50 PM

Quote:

Originally Posted by Nata (Post 473474)
...to find out if app runs.

There may be a better way, but this shell script works for me:
Code:

ps -x | grep '/Address Book.app/' | wc -l
If the result is 1, it isn't running. If it's 2, it is.

baf 05-31-2008 03:28 PM

I would recommend that the ps part be:
Code:

ps -ax -o command
this makes you see other users processes which you otherwise would miss.
Also only outputs the command name so it has to do less digging in kernel data.
and the grep part:
Code:

grep '[A]larm Clock'
If you do it like this you avoid catching the grep process and the answer from
Code:

ps -ax -o command|grep '[A]larm Clock'|wc -l
will be zero when not running
otherwise it's the number of processes for that name

hayne 05-31-2008 03:38 PM

See the various solutions suggested (for determining if a particular app is running) on DaringFireball.net: http://daringfireball.net/2006/10/processing_processes

See also the two versions of the app_running script on my Bash scripts page: http://hayne.net/MacDev/Bash/

Mikey-San 05-31-2008 05:07 PM

Quote:

Originally Posted by baf (Post 473494)
I would recommend that the ps part be:
Code:

ps -ax -o command
this makes you see other users processes which you otherwise would miss.

Whether or not you need to do this depends entirely on why you need to know if an app is running in the first place.

Nata 06-03-2008 04:24 PM

I did in such way:
tell application "Address Book"
set itRuns to it is running
if not (itRuns) then
activate
end if
-- add some addresses
if not (itRuns) then
quit
end if
end tell
And so with other apps. Main problem was to run these scripts from specific app that runs them under root. Now it's over.
Thanks to all.

Mikey-San 06-11-2008 07:03 PM

Quote:

Main problem was to run these scripts from specific app that runs them under root.
What are you doing with GUI apps running as root? This is a bad idea.

hayne 06-11-2008 09:42 PM

Quote:

Originally Posted by Mikey-San (Post 475877)
What are you doing with GUI apps running as root? This is a bad idea.

I agree - it is a very bad idea to run GUI apps as 'root'. Anything that requires 'root' privileges should be done by a small command-line tool that is invoked as needed by the GUI app.

Nata 06-12-2008 02:36 PM

This app is our installer that runs some tasks. And if some of them have to be performed under root (installing widgets), it performs all tasks under root.
This is bug that nobody will fix in near future, and we have to do workarounds.

hayne 06-12-2008 02:50 PM

Quote:

Originally Posted by Nata (Post 476029)
This app is our installer that runs some tasks. And if some of them have to be performed under root (installing widgets), it performs all tasks under root.
This is bug that nobody will fix in near future, and we have to do workarounds.

Tell us what your product is called so we can recommend against installing it.
:)

Mikey-San 06-12-2008 03:09 PM

Quote:

Originally Posted by Nata (Post 476029)
This app is our installer that runs some tasks. And if some of them have to be performed under root (installing widgets), it performs all tasks under root.

You should be using a GUI-less helper tool to install your software. Have you read any of the (extensive) installer and security documentation from Apple?

It sounds like you aren't using a standard installer package, either. Why not?

Quote:

This is bug that nobody will fix in near future, and we have to do workarounds.
What, exactly, are you calling a bug? The fact that you shouldn't be running a GUI app as root? That you can't gain elevated privileges for your GUI app after it launches under a lower-privilege user?

Quote:

Tell us what your product is called so we can recommend against installing it.
Agreed with Hayne.

Nata 06-12-2008 03:38 PM

Quote:

You should be using a GUI-less helper tool to install your software. Have you read any of the (extensive) installer and security documentation from Apple?
I have no idea about this. We don't use PackageMaker. This is our internal product, although we released lots of installers created with it.
I mean bug in installer is that when one of the tasks requires higher permissions, all of the tasks are performed with these highest permissions.

Mikey-San 06-12-2008 03:43 PM

Quote:

Originally Posted by Nata (Post 476040)
I have no idea about this.

Yet, you're working on the installer? You still haven't explained why you don't use Apple's standard installer system. It's very rare that anyone should need to roll his or her own installer. (And it requires good knowledge of what and what not to do. I've had to custom-roll them before, and it's really something you want to avoid unless you have no choice.)

Quote:

I mean bug in installer is that when one of the tasks requires higher permissions, all of the tasks are performed with these highest permissions.
Does not compute. Please explain what you mean.

Nata 06-12-2008 04:17 PM

Quote:

You still haven't explained why you don't use Apple's standard installer system.
This is request of our director to use our installer instead of Apple's installer.
Quote:

Does not compute.
As my native language is not English, it's a bit difficult task.
For example, installer has to perform such tasks: install app into /Applications, widget into /Library/Widgets, importer into /Library/Spotlight, music into ~/Music etc. and do some additional tasks: add installed music to iTunes.
Installing widget requires authorization even if it runs under admin. And then all tasks are performed under root.
But actually I just found that there is option in installer for each task to specify which permissions it requires. And if set to perform with lowest permissions it works fine.
So it will be a good lesson for me.
Anyway I will remember to not using Finder in apple scripts if possible and to use POSIX file.

Mikey-San 06-12-2008 04:28 PM

Quote:

Originally Posted by Nata (Post 476046)
As my native language is not English, it's a bit difficult task.

It wasn't a language problem, it was a verbosity problem. The extended explanation you gave this time is clear and informative, whereas what you said before wasn't. :)

Quote:

Installing widget requires authorization even if it runs under admin. And then all tasks are performed under root.
It's only doing that because you're running the GUI app as root. If you use a helper tool that performs the copying, and just invoke that tool as root, you can leave the GUI running under the normal user account and do only what you need as root.

Quote:

But actually I just found that there is option in installer for each task to specify which permissions it requires. And if set to perform with lowest permissions it works fine.
It sounds like whoever wrote your installer system may have taken care of the "don't run GUI as root" problem, but without knowing more about this installer program, I couldn't confirm or disconfirm that.

To be candid, your director should understand that Apple's already written a great installer system that his company doesn't have to maintain, and that users are comfortable with because it's standard and easy to use. And it's probably better than what he had his people build. We're also generally more trusting of Apple's installer system, because it avoids problems like the one we're talking about.


All times are GMT -5. The time now is 05:54 AM.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2014, vBulletin Solutions, Inc.
Site design © IDG Consumer & SMB; individuals retain copyright of their postings
but consent to the possible use of their material in other areas of IDG Consumer & SMB.