I am trying to store a reference to a finder item in a database to be retrieved later. This would be very simple, except I would like this to work even if the item is moved or renamed - same as it does when you have an alias file pointing to the item.
I can’t seem to find any usable information regarding what exactly is stored inside an alias file, how to get it and how to use it to get back to the original item.
Any ideas would be appreciated, as I would like to avoid having to create actual alias files and storing these.
Well applescript’s only serialisation of object is store and load script commands. So without separate files it won’t work but you can store a serialised script object inside a record of your database. Not sure which kind of data you’re using but it is possible. Also for text databases you could use base64 encoding and decoding and for binary database (like mysql) you can use cpio to store it in the record to be sure that everything is decoded correctly.
Uhm… I am not sure what “a serialised script object” is and where does one go to get one?
Hi. An alias”not to be confused with an alias file”has internal tracking, but I don’t immediately see a way to incorporate that into a database, unless it were of the faceless Applescript type. Like DJ Bazzie intimated, you may need to have separate files… the database, and a file tracker.
After modifying the filename, save this as an app. Let it work once and then move the file somewhere else on your machine. Run it again.
property isTracked : {}
tell application "Finder"
if isTracked = {} then set isTracked to (file "green simp.ai") as alias --insert a file's filename living on your desktop
try
select isTracked
end try
end tell
Well, that’s kind of what I want to do, except for the part of saving the file…
The piece that I am missing is the one stored inside that saved app - which I believe is the same as the one being stored inside an alias file: a unique and persistent file ID that I could store as text, then retrieve it and pass it back to Applescript.
Serializing is a way of storing data. What it’s mean is that you have an object in your programming and can store it somewhere and load it later without any difference (this is where you’re looking for). Object are normally only inside a programming and can’t be used outside directly. The serialising is mostly used to send objects over network, store it on a hard drive or communicate between applications. The only thing is that Applescript’s serialisation isn’t so great as for Objective-C for instance.
Thanks. As I said in the opening, I don’t want to store files - whether alias files or AS apps (not to mention the original files).
I think I may have made some progress on this. That is, I believe the following retrieves the number I am looking for:
tell application "Finder"
set myFile to (choose file)
set myPath to quoted form of POSIX path of myFile
do shell script "/usr/bin/stat -f %i " & myPath
end tell
Now, if I only could (a) find a way to reverse the process and turn the inode number back into a path and (b) get someone to confirm that this is indeed doing what I think it is…
Inode number is not static.
Simple test:
- create text file
- read inode number
- open, add text, save
- read inode number - it changed
A quick trawl of the web suggests that you’d want the HFS file id, available from the disk’s ‘catalog file’.
I don’t know of any way to do this with either AppleScript or CLI.
That is also not what I said. You need to store it, serialize it, the read the serialized data and put it into a record of your database.
You can’t open a file by it’s inode number for security reasons. If you can open a file by it’s inode number you could go around the security of your file system. What you can do is using find to find a file by it’s inode number but to go through your whole file system takes a lot of time. What alastor say is right about text edit but the same rule is applied for alias because text edit creates a new file when you save it.
An alternative is CFM (Carbon File Manager) who can open files by it’s CNID (Catalogue Node ID). Note that CNID is not the same as BSD file managers inodes. A single file can have CNID number that is different from the inode number. The alias in applescript is for example a stored CNID as a property. To make life simpler it would be much more easier to store a script object in a seperate file so the CNID is stored properly and the CFM is called automatically when it’s needed. Basically you’re just trying to do this for yourself and I think you can’t do this in Applescript only, you’ll need other command line utilities like HFS Debug (who only works for HFS+ file systems) or you need to go to C++ programming as well.
Ah. Well, so much for that. Thanks for saving me from following the wrong trail.
But what would I do with it when the time comes to retrieve the original file? I am afraid I may not have made my point about not storing files quite clear. Currently, I can do the following:
On Store:
- Select a file
- Make an alias file to the selected file at temp folder
- Store the alias file in database
On Retrieve:
- Export the alias file to temp folder
- Open the alias file (thus opening the original file)
This would work for me reasonably well, I think. I am just trying to eliminate all the middlemen in the process and reduce it to something like:
On Store:
- Select a file
- Get the alias to the selected file as text
- Store the text in database
On Retrieve:
- Get the stored text as alias
- Open the alias (thus opening the original file)
If it’s not possible to get the [whatever an alias file keeps inside], then I’ll just store the alias files themselves - but it is not “simpler” for me.
That’s not what I see (I am referring to an alias file). In any case, most of my files are PDFs - so my main worry is renaming and moving.
Well it’s not like an alias (in a file or in applescript, they are both the same) is a ticket you get from the file system and use it later to locate a file. An alias file can only be created with the Finder in Mac OS X. An alias object can be created with core services alias manager or in applescript.
also notice, because you were also working in the bsd file system, that there is no such thing as a table that contains the file’s location, node and name because they are all stored at different places in your file system. There is no direct relation between them and therefore it is hard to resolve a file name by it’s node id. There is a node table, file’s name is stored in directories and the pointers to blocks (pointers to the actual data) is stored in inside a node. The only place on a hard drive (BSD) where a file name matches it’s node id is inside a directory and that’s what find does when you search a file by it’s node (it opens all directories, reads them and compare the node id).
Yes, I think we have established that. But then what exactly is it? Obviously it contains something that points to the original file. Saying it can only be created by Finder or by Applescript doesn’t help me to get at that something.
Just a thought: “locate”. It appears you can make it work with a customised database. With the proposed modifications it will only search the directories you specify. Possibly even set up multiple copies for as many purposes. I can’t claim, though, to understand all of it, with one reading…
I take it that aliases (AppleScript «class alis») can’t be stored in your database directly, but only text or entire files.
It’s possible to reclassify alias data as text data and back again by means of the File Read/Write commands. The demo script below works for me so far, but I’m nervous about the possibility of corruption in the conversions between the notional ‘string’ text in the temporary files and the Unicode text within the script. Just storing the data as data would be better if your database could do it:
-- Demo.
tell application "Finder" to set originalAlias to (item 1 of (get selection)) as alias
-- Reclassify the alias data as text data (or preferably just as data).
set fref to (open for access file ((path to temporary items as text) & "Alias data.dat") with write permission)
try
set eof fref to 0
write originalAlias to fref
set dataForDB to (read fref from 1 as string) -- Or preferably: set dataForDB to (read fref from 1 as data)
end try
close access fref
beep
-- delay 20 -- Use this delay to drag the selected file somewhere else, if you want to test the efficacy of the reconstructed alias.
-- Take the text data, write them to file as (non-Unicode) text and reclassify the result as alias data.
set fref to (open for access file ((path to temporary items as text) & "Text data.dat") with write permission)
try
set eof fref to 0
write dataForDB to fref as string -- Or if 'dataForDB' is data: write dataForDB to fref
set restoredAlias to (read fref from 1 as alias)
end try
close access fref
restoredAlias
It’s not really much different from what you’re doing already. Either way, you’re better off storing the complete alias (by whatever means) than trying to isolate some “active ingredient”.
That’s what I’m saying that a hard link or alias have a node pointer. An hard link can be made by the file system but also by the file system only. You can also not say that you want a file in a variable, no you put one of it’s properties or it’s data in a variable, it’s obvious that this also applies for hard links or aliases. An alias object can be created in applescript (how in technical detail I don’t know) with the alias manager in the core services. The alias manager is able to lookup a file’s name from it’s node through volfs. But again without using a file I it won’t work because it’s designed to be a file.
I am not sure about that. In what form would I get an ‘alis’ object? I see that just about any reference to an alias resolves to the original file - so if told my DB application to set cell X to myAlias, I would end up with the original file being stored in the cell.
AFAIK, an alias is a record - but again, I can’t get it as such.
I am afraid I don’t follow you. Surely, the alias manager is able to resolve an alias without the alias being in a file. Otherwise this wouldn’t work (it does):
tell application "Finder"
set myAlias to (choose file) as alias
delay 20 --rename and/or move the chosen file
select myAlias
end tell
How can it be stored even if you shutdown your computer? Does that ring any bells? For me it does because it means that your script stores an alias file on your hard drives and connect it to the alias object in applescript (that’s why an alias file and applescript alias are the same). An alias behaves like a property so there is are data files connected with your script for resources otherwise an alias would be empty after a restart of your system. Creating an alias in applescript creates an alias file on your hard drive as well and that alias file is static while the file where it points to can be dynamic.
Where exactly is this file? AFAIK, if I create an alias in Applescript, it is lost as soon as I close the window (perhaps even sooner).