How to Set the Attach Directory Prefix for Org-Mode 9.3
TL;DR: There are two methods org-attach.el uses to determine where to store attachments, org-id and org-dir. I prefer org-id but also want to be able to specify the ./data directory prefix.
Thus:
* This will use =~/.charnock/data/4B/B068CA-8948-49F1-9C27-284FAA4E8B05/<attachment>= for its attachments :PROPERTIES: :ID: 4BB068CA-8948-49F1-9C27-284FAA4E8B05 :END: # Local Variables: # org-use-property-inheritance: nil # org-attach-use-inheritance: (quote selective) # org-attach-id-dir: ~/\.charnock/data # End:
Or, if you want a DIR Property based solution:
#+PROPERTY: DIR ~/.foo/bar * An entry that will use the inherited DIR property * An entry that overrides the DIR property. :PROPERTIES: :DIR: ~/.bar/foo :END: This entry will place attachments /directly/ in =~/.bar/foo<attachment file>=, /not/ =~/.bar/foo/XX/XXXXXXXXXXX/<attachment file>=. * As far as I know this entry will /still/ use the =DIR= property because it takes precedence over =ID= :PROPERTIES: :ID: BLOOFY-FLOOFY-JUICY-GOOSEY :END: # Local Variables: # org-use-property-inheritance: (quote ("DIR")) # org-attach-use-inheritance: (quote selective) # End:
I've been working on a small side-project to track and manage my information archive/wiki. I thought it would be fun to attempt to do this in Emacs org-mode and so far at least I haven't been wrong.
My wiki is an Org file that is partially populated by a directory in which I save repositories, videos, audio files, html, etc. that I find interesting. The Org entry for each one consists of a heuristic creation time and my thoughts on it, among other things. I express the attachment to the file, if there is one, by using org-attach.el's symlink support. org-attach, by default, maintains its attachments in a directory ./data alongside whatever org file you're editing. Beneath that a tree of hash prefixes is laid out. Partly because I wanted to maintain this particular Org file in Dropbox which has, shall we say, complicated, support for symlinks and partly because I think that maintaining a layer of indirection here allows the Org file to move while the attachments can stay put, I wanted to move the ./data attachment directory prefix somewhere else.
org-attach.el claims to support this so I went about following its advice and ran headlong into how little I understanding about Properties/Keywords/In-buffer Settings/etc.
I have always found this topic in org-mode to be confusing. I find the manual to be a bit vague on this point so, unfortunately, I often just thrash till it 'works' and then discover something subtle that I did wrong later. This time I figured I'd sit with it a bit more and ask for some clarification and I think it's paid off.
The manual states:
It is often useful to associate reference material with an outline node… [One] method is attachments, which are files located in a directory belonging to an outline node. Org uses directories either named by a unique ID of each entry, or by a 'DIR' property.
By default, org-attach will use ID properties when adding attachments to outline nodes. This makes working with attachments fully automated. There is no decision needed for folder-name or location. ID-based directories are by default located in the 'data/' directory, which lives in the same directory where your Org file lives(1). For more control over the setup, see *note Attachment options.
'org-attach-id-dir'
The directory where attachments are stored when 'ID' is used as method.
'org-attach-use-inheritance'
Inheritance works the same way for both 'ID' and 'DIR' property. If both properties are defined on the same headline then 'DIR' takes precedence. This is also true if inheritance is enabled. If 'DIR' is inherited from a parent node in the outline, that property still takes precedence over an 'ID' property defined on the node itself.
The library code itself is a little less scattershot:
;; Attachments are managed either by using a custom property DIR or by ;; using property ID from org-id. When DIR is defined, a location in ;; the filesystem is directly attached to the outline node. When org-id ;; is used, attachments are stored in a folder named after the ID, in a ;; location defined by `org-attach-id-dir'. DIR has precedence over ID ;; when both parameters are defined for the current outline node (also ;; when inherited parameters are taken into account).
I initially just fixated on the notion that org-attach-id-dir must be the same thing as the DIR property. This, it turns out, is not the case. DIR the property, if set for a particular node either directly or via inheritance, is a different attachment mechanism entirely, completely replacing the ./data/HA/HASH based directory structure set up by the default option. org-attach-id-dir is the variable that defaults to ./data but can be used to establish a new parent for the ID based attachment tree of org-id.
The components involved, then, are:
org-attach-use-inheritance (and thus org-use-property-inheritance)
Because I wanted to set this 'option' at the file level, I thought I needed to utilize some form of inheritance, and both of these variables are in play to do that. org-attach-use-inheritance defaults to 'selective which means to reference org-use-property-inheritance. org-use-property-inheritance defaults to nil which means, as you may have guessed, "Don't use inheritance".
One solution branch I explored here was to set org-use-property-inheritance to '("DIR") which means that I allow the use of property inheritance but only for the DIR property. Again, because I wanted to override the ./data directory location this was barking up the wrong tree but it's still useful to understand. If Org did allow me to change this behavior via properties this is how I could've done it.
The DIR and ID properties.
These properties can be defined at any level of the Org file, but to set them off-node you need to allow property inheritance, and DIR takes precedence over ID.
DIR means to abandon the automatic hash based attachment directory entirely and just use "this literal directory" for your attachments.
ID means "use the org-id strategy and make this string the thing you mangle to figure out where to put me under org-attach-id-dir".
In-Buffer Settings.
In-buffer Settings are interesting. I still don't know what defines what they can and can't be. There are several 'special' In-Buffer Settings, like AUTHOR, LINK, SETUPFILE, etc.
Some of these are particularly confusing because they can also be set as tree properties. But whene they're specified at the file level they seem to be referred to as Keywords.
You set these keywords via #+<KEYWORD> foo anywhere in the file. They don't need to be at the top or bottom. They don't need to be at the start of the line. If you set them anywhere (or multiple times!) they take effect for the whole thing.
The particularly relevant bit here is the #+PROPERTY: Property_Name Value Keyword. This is what really tripped me up for a good long while. To my eyes at least, #+PROPERTY read like #+<PROPERTY> but that is decidedly not the case. I'm not sure how I thought that in hindsight but the mind is a funny thing. The key (if you were doing a DIR based solution here) is that PROPERTY is the 'Keyword' and DIR is the 'Property' and ~/.foo/bar/bat is the 'Value'. So while I thought it was something like #+DIR: ~/.foo/bar/bat somewhere in the file it actually needed to be #+PROPERTY: DIR ~/.foo/bar/bat.
file-local variables
Because Org mode only exposes alteration of the org-attach-id-dir variable as a literal variable and not a property, the solution here is actually to use Local Variables. This is a mechanism where, with some specially formatted text in special locations in the file, you can set some variables every time any Emacs visits the file. This has the disadvantage of, depending on the variable, popping up a warning about the file setting some variables, but in this case it looks like org-attach-id-dir is marked as safe and so you don't get the warning.
So let's put it all together now:
If you want a DIR Property based solution:
#+PROPERTY: DIR ~/.foo/bar * An entry that will use the inherited DIR property * An entry that overrides the DIR property. :PROPERTIES: :DIR: ~/.bar/foo :END: This entry will place attachments /directly/ in =~/.bar/foo<attachment file>=, /not/ =~/.bar/foo/XX/XXXXXXXXXXX/<attachment file>=. * As far as I know this entry will /still/ use the =DIR= property because it takes precedence over =ID= :PROPERTIES: :ID: BLOOFY-FLOOFY-JUICY-GOOSEY :END: # Local Variables: # org-use-property-inheritance: (quote ("DIR")) # org-attach-use-inheritance: (quote selective) # End:
Or if you wanted to stick with org-id but wanted to change the directory prefix:
* This will use =~/.charnock/data/4B/B068CA-8948-49F1-9C27-284FAA4E8B05/<attachment>= for its attachments :PROPERTIES: :ID: 4BB068CA-8948-49F1-9C27-284FAA4E8B05 :END: # Local Variables: # org-use-property-inheritance: nil # org-attach-use-inheritance: (quote selective) # org-attach-id-dir: ~/\.charnock/data # End:





