Ghost file stays open even when trashed

open and close statements must be balanced.
You cannot write a close statement without a preceding open statement

:frowning: I thought it was fixed, but now it’s doing the same thing again.

I pasted in Stefan’s code just in case I mistyped or something, and it no longer works.

New file, wrote to it once before OK., but now after error before closing the file, I get the “already open” error no matter what I do using my code or Stephan’s. Trashed the file - still same thing. This is getting weird.

:expressionless: OK., it works … Never noticed Finder do this before …

When I rewrote a text file before, I could see the update immediately in the file preview. This time however, that did not happen until I backed out of the folder, came back to it, and then the file preview showed the update. And it continues to update each time.

Not that it’s extremely important, but does anyone know why that happened?

Thanks again!

in case of an accidentally opened file put this at the beginning of the script


set thisFile to file aFilePath
try
	close access thisFile
end try

it ignores the error.

But that’s no solution for “production”
You have to ensure in your script that each open statement is reliably balanced with a close statement

PS:

if aFilePath is a HFS string path this syntax is correct


set thisFile to file aFilePath
close access thisFile

however if aFilePath is an alias or file specifier (for example the result of choose file) the syntax is


close access aFilePath

Hi Lou,

I have seen this in the past. i.e. where you trash a file that was opened with ‘open for access’. Can’t remember what was the way to close it, but there was an easy trick to it. Let me think about it.

Later,
kel

I think DJ is right and you need to quit Script Editor, but still thinking that there was another way before I quit Script Editor.

Yes, DJ’s was the way I think. It’s like the application remembers what was ‘open for access’ with the reference number. Sorry about that! :slight_smile:

gl,
kel

Hey Lou,

Use a handler to write to files - one that has a proper error-handler.

------------------------------------------------------------------------------------
--» writeFile()
------------------------------------------------------------------------------------
--  Task: Write to a file as a specific data-type.
--  dMod: 2012/10/26 20:00
------------------------------------------------------------------------------------
on writeFile(srcData, targetFile, startPosition, dataType)
	try
		set fileRef to open for access targetFile with write permission
		if startPosition = 0 then
			set eof of fileRef to 0
		end if
		write srcData to fileRef as dataType starting at startPosition
		close access fileRef
	on error errMsg number errNum
		try
			close access fileRef
		end try
		error "Error in handler: writeFile of library: gen.lib" & return & return & errMsg
	end try
end writeFile

------------------------------------------------------------------------------------
--» writeUTF8()
------------------------------------------------------------------------------------
--  Task: Write text to a file and overwrite any content.
--  dMod: 2012/10/26 20:00
------------------------------------------------------------------------------------
on writeUTF8(_text, _file)
	try
		if _file starts with "~/" then
			set _file to POSIX path of (path to home folder as text) & text 3 thru -1 of _file
		end if
		set fRef to open for access _file with write permission
		set eof of fRef to 0
		write _text to fRef as «class utf8»
		close access fRef
	on error e number n
		try
			close access fRef
		on error e number n
			error "Error in writeUTF8() handler!" & return & return & e
		end try
	end try
end writeUTF8

------------------------------------------------------------------------------------

Hi Lou,

Yes, as everyone has written, It’s better to write safe code. The thing is, sometimes you get into these situations and don’t know how to exit from it and the best way to do it as DJ wrote is to quit the app. If you are ever stuck, then force quit the app.

Man, I was sure there was a way to close the file by AppleScript. Still thinking about that.

BTW, this is an old problem when using the read/write scripting addition.

gl,
kel

Nice handlers Chris.

How did you figure out that the open for access command takes posix paths? :slight_smile:

Thanks Tommy.

I think I was writing an example script by hand (no libs) for someone who preferred posix paths, and I had forgotten the exact syntax for write. So I looked it up in Script Debugger and saw the reference for to:

to	required	any	the file reference number, alias, or file reference of the file to write to

File Reference caught my eye, and it occurred to me that I hadn’t tested in many years what formats it would tolerate ” so I made the example script into a test routine.

set testFldr to ((path to home folder as text) & "test_directory:TEST_FOLDER:")
try
    alias testFldr
on error
    do shell script "mkdir -p " & quoted form of (POSIX path of testFldr)
    delay 0.1
end try
do shell script "open " & quoted form of (POSIX path of testFldr)
delay 1
set testHFSPath to testFldr & "test_file_1.txt"
set testPosixPath to (POSIX path of testFldr) & "test_file_2.txt"
set testPosixHomePath to "~/test_directory/TEST_FOLDER/test_file_3.txt"
set testPosixFile to POSIX file (POSIX path of testFldr & "test_file_4.txt")

writeMe("Test_File_01_HFS_Path", testHFSPath)
delay 0.2
writeMe("Test_File_02_Posix_Path", testPosixPath)
delay 0.2
writeMe("Test_File_03_Posix_Home_Path", testPosixHomePath)
delay 0.2
writeMe("Test_File_04_Posix_File", testPosixFile)

on writeMe(_text, _file)
    try
        set fileHandle to open for access _file with write permission
        write _text to fileHandle as «class utf8»
        close access fileHandle
    on error e
        try
            close access fileHandle
        end try
        e
        "" --» Stub for break-point in Script Debugger
    end try
end writeMe

I was delighted to find out that Posix Paths were supported and disappointed that home-based-Posix-Paths were not, but the latter was an easy fix.

Well you shouldn’t close the file by reference Chris and should use StefanK’s example as I have mentioned earlier. If opening the file causes an error no file descriptor will be returned. So the rule is that In the error block you always close the file by using it’s path, never by it’s descriptor.

The AE framework did get some new features a few OS X versions back. As an scripting addition writer myself I don’t need to take posix files into consideration, the AE framework does that for me. It’s therefore not really a open for access feature but for many different commands as long as it allows implicit coercions. So when I want an AppleEvent descriptor as fileTypeUrl the AE framework will try to coerce the given argument if it’s of class string containing a POSIX or a HFS path. So you’re maybe glad to hear that it’s not only open for access that supports POSIX paths but a lot of more commands like deprecated info for and deprecated list folder :slight_smile:

Hello.

@ Chris, it is great that you figured it out.

It is good to still learn something new, especially how file reference can be interpreted. :slight_smile:

@ DJ Bazzie Wazzie: Thanks for the info, It is also nice to have learned that the correct way of trying to closing a file is to use its full path. Kudos to Stefan for bringing that onto the table. (It covers most cases, and is probably most convenient when you edit the code, espcecially when you are in an editor, that doesn’t take care of leaked file handles, or reference numbers. I see an advantage of writing code, so others can play with it, without being shot in the back, by suddenly having a file they can’t open.

By the way: I can’t see that list folder is deprecated.

Thanks a lot guys. :slight_smile:

And even applications that use Cocoa scripting. But it’s worth keeping in mind that anything sandboxed needs file references, not just paths.

Hi.

Here’s some logic over which to mull:

  1. ‘close access’ + file specifier closes an unspecified access to the file, provided that the access is owned by the application running the script. If the application has several accesses open to the file, ‘close access’ + file specifier will close one of them, but you can’t know which.

  2. ‘open for access’ without write permission will only ever error if the path to the file’s incorrectly specified. In this case, using ‘close access’ ” whether with the incorrect file specifier or with the non-existent ‘open for access’ number ” is a waste of time.

  3. ‘open for access with write permission’ will only ever error if the path’s incorrectly specified as above or if the file’s already open with write permission. If some other application owns the write permission access, the script won’t be able to close it, so again using ‘close access’ is a waste of time. If the write permission access belongs to the script and is left over from a previous run, ‘close access’ + file specifier may close it, but it depends on point 1 above.

My own view is that it would be better to catch ‘open for access’ errors separately so that their causes can be investigated and fixed. If they’re the script’s fault, it would be better to fix the code causing them than blindly to close accesses. Something like the following, although I don’t usually bother with the first ‘try’ block myself:


try
	set fileDescriptor to (open for access file aFilePath with write permission)
on error errMsg
	display dialog errMsg buttons "Stop" default button 1 cancel button 1
end try
try
	write stuff to fileDescriptor
	-- do other stuff
on error errMsg
	display dialog errMsg buttons "Stop" default button 1
end try
close access fileDescriptor

From the description:

Of course that’s very old…

And there’s always:

use framework "Foundation"
(current application's NSFileManager's defaultManager()'s contentsOfDirectoryAtPath:posixPath |error|:(missing value)) as list

Thanks, I thought it would but wasn’t sure.

@Nigel: If an error occurs while writing and the script hangs (read: write command doesn’t have a timeout) or unexpectedly quits, the second run your example code won’t be able to close the file properly because in your example you only close the file by it’s descriptor. I understand the problem of closing an file with read access opened by another application, but that is solved with an extra try around the closing in Stefan’s post.

How awkward, now I saw it clearly, I actually did, believe it or not, look it up in the Scripting Additions dictionary.

@Nigel, it of course depends on who it is sitting there, having problems with a file handler one can’t close. Say if one that hasn’t experienced this problem before, sits there, then it is better to close the file reference all together, so that the person in question can move on, without the befuddlement. And thanks for the writeup. :slight_smile:

Other thing is file reference of file system, and other thing - file descriptor (of current application, many users name its variable fileRef, but its correct name is fileDescriptor for example).

This should close your opened descriptor (that is, to force the current application to forgot the file descriptor)

close access fileDescriptor

– close stored in the script file descriptor

If in advance, when opening a file for access, you did not save this descriptor to the script variable (fileDescriptor), then this means: your script has completely lost control over the file descriptor. In this case, you will have to restart the application for it to close all file descriptors.

Hi KniazidisR.

Please don’t keeping replying to topics that ended months or years ago. I’ve asked you many times.