Ghost file stays open even when trashed

How do I close this file?

1. I access a file in AS alone, like so:

set thisFile to open for access aFilePath with write permission write stuff to thisFile -- do other stuff close access thisFile
I have no problems with this script, as long as “do other stuff” runs and “close access” is hit. BUT:

2. If there’s an error in “do other stuff” and “close access” is not hit, I end up with a worthless file, that pops an " . already open error" if I try to open it again.

3. So I try to close it:

set thisFile to file aFilePath close access thisFile
and I get an error on the second line " … can’t make . [thisFile] . type file". If “thisFile” is a file on the line above, why is it no longer on the second?

4. I trash the file and same thing, the system remembers the file name and has flagged it as open (apparently). Ghost file.

Brief: I cannot close the file except as in 1 above, not afterwards. If 1 doesn’t run, I cannot use that file name again.

Question: How can I close or delete this file or tell the system it doesn’t exist?

Thanks so much for your help.

Hi,

standard procedure assuming aFilePath is a HFS path (colon separated)


try
	set fileDescriptor to open for access file aFilePath with write permission
	write stuff to fileDescriptor
	-- do other stuff
	close access fileDescriptor
on error
	try
		close access file aFilePath
	end try
end try

What you might want to check is if the file was already opened. When you rerun the program if the file was already open then you’ll get errors and it needs to be closed.

If I’m way off then disregard. Just checking.

gl,
kel

btw, an easy way to close a file that has been opened through AppleScript is:

set f to choose file
close f

gl,
kel

StefanK’s example is indeed the standard procedure. But here some explanations to make it clear what happens.

First of all you open a file with write permission. The difference is that write permission can be opened once in the entire operating system while read permission can be opened as many times as you want. When opening a file with write permission you have to be more careful because leaving a file opened with write permission causes the file to not being editable.

Secondly AppleScript is not opening the file because it can’t, it’s handled by a scripting addition which lets the fileaccess commands be handled by the application running your script. When you quit an application, all opened files are automatically closed. But the problem is that when an AppleScript is finished, the application running your script doesn’t have to be closed at all (like script editor). That means that when you don’t properly close a file with write permission nobody can open that file with write permission afterwards (including removing it from your file system). File access commands are limited to current application you need to quit the application running your script when it keeps a file with write permission opened.

Again, you can avoid all these problems by using StefanK’s example code.

Stefan …

This makes me crazy. Your snippet worked, but I had tried what I was sure was the same thing and it wouldn’t.

Q: can you tell me why my two lines:

set thisFile to file aFilePath close access thisFile
wouldn’t work?

Thanks for the reply. The files seem to be behaving themselves for the moment.

kel1 …

Thanks for the reply. Part of what I was asking is that if the file is gone and trashed, what does it mean to say the file is open, as the system apparently did.

Anyway, they’re behaving now but I’d sure like to understand what happened and why

set thisFile to file aFilePath close access thisFile
wouldn’t work for me.

I got a “can’t make … [thisFile] … into type file” error on the second line, not the first. How can AS pass through the first line if “thisFile” is not a valid path? And why does it fail on line two?

Thanks again very much for the help.

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: