Hi all, I have written this simple function to move or rename a destination file in an external link at point. I share it here in case it is useful to someone. Best regards, Juan Manuel #+begin_src emacs-lisp (defun my-org-replace-link-file (from to) (save-excursion (goto-char (point-min)) (while (re-search-forward org-bracket-link-regexp nil t) (when (string-match-p from (match-string 1)) (replace-match (concat "[[file:" to "]]")))))) (defun my-org-rename-link-file-at-point () "Rename or move a file in an external link at point and update the link path" (interactive) (let* ((curr-dir (abbreviate-file-name default-directory)) (current-path (org-element-property :path (org-element-context))) (new-path (read-file-name "Rename file at point to: " current-path))) (rename-file current-path new-path) (message (concat "moved to: " new-path)) (if (directory-name-p new-path) (setq new-path (concat new-path (file-name-nondirectory current-path))) (setq new-path new-path)) (my-org-replace-link-file current-path (replace-regexp-in-string curr-dir "" new-path)))) #+end_src
[-- Attachment #1: Type: text/plain, Size: 390 bytes --] >>> "JMM" == Juan Manuel Macías <maciaschain@posteo.net> writes: Hi Juan Manuel > Hi all, > I have written this simple function to move or rename a destination file > in an external link at point. I share it here in case it is useful to > someone. Thanks, that looks very useful, I tend to reorder files in subdirectories and therefore «destroying links» Uwe Brauer [-- Attachment #2: smime.p7s --] [-- Type: application/pkcs7-signature, Size: 5673 bytes --]
On 05 March 2022 19:58, Juan Manuel Macías <maciaschain@posteo.net> wrote:
Hello Juan!
> Hi all,
>
> I have written this simple function to move or rename a destination file
> in an external link at point. I share it here in case it is useful to
> someone.
>
> Best regards,
>
> Juan Manuel
>
> #+begin_src emacs-lisp
> (defun my-org-replace-link-file (from to)
> (save-excursion
> (goto-char (point-min))
> (while (re-search-forward org-bracket-link-regexp nil t)
> (when (string-match-p from (match-string 1))
> (replace-match (concat "[[file:" to "]]"))))))
>
> (defun my-org-rename-link-file-at-point ()
> "Rename or move a file in an external link at point and
> update the link path"
> (interactive)
> (let* ((curr-dir (abbreviate-file-name default-directory))
> (current-path (org-element-property :path (org-element-context)))
> (new-path (read-file-name "Rename file at point to: " current-path)))
> (rename-file current-path new-path)
> (message (concat "moved to: " new-path))
> (if (directory-name-p new-path)
> (setq new-path (concat new-path (file-name-nondirectory current-path)))
> (setq new-path new-path))
> (my-org-replace-link-file current-path
> (replace-regexp-in-string curr-dir "" new-path))))
>
> #+end_src
>
Thanks for sharing! It'd be great if it worked for attachments as well,
but that is a whole can of worms.
Cheers,
--
João Pedro de Amorim Paula
IT undergraduate at Universidade Federal do Rio Grande do Norte (UFRN)
Hi João, Thanks for your comment.
João Pedro de Amorim Paula writes:
> Thanks for sharing! It'd be great if it worked for attachments as well,
> but that is a whole can of worms.
Regarding attachments, do you mean org attachments or email attachments?
Could you give an example of a use case?
Best regards,
Juan Manuel
On 10 March 2022 14:58, Juan Manuel Macías <maciaschain@posteo.net> wrote: > Hi João, Thanks for your comment. Hello, Juan! I apologize for the delay on responding, I had some issues with my e-mail account lately. > Regarding attachments, do you mean org attachments or email attachments? > Could you give an example of a use case? I mean org attachments. I use org-attach extensively to store documents with notes. So I'd have a heading like so * Documents :PROPERTIES: :DIR: data/docs/ :END: - [[Registration][attachment:registration.pdf]] :: My registration. And say I'd like to rename the file. I would need to rename it inside data/docs and I would also need to edit the link, so I would like to have a way to do it automatically. I just got a computer back so I will be trying to adapt what you did to work with org-attach, but if you figure out a way to do it as well, please, let me know. Regards, -- João Pedro de Amorim Paula IT undergraduate at Universidade Federal do Rio Grande do Norte (UFRN)
Hi João,
João Pedro de Amorim Paula writes:
> I mean org attachments. I use org-attach extensively to store documents
> with notes. So I'd have a heading like so
>
> * Documents
> :PROPERTIES:
> :DIR: data/docs/
> :END:
>
> - [[Registration][attachment:registration.pdf]] :: My registration.
>
> And say I'd like to rename the file. I would need to rename it inside
> data/docs and I would also need to edit the link, so I would like to
> have a way to do it automatically. I just got a computer back so I will
> be trying to adapt what you did to work with org-attach, but if you
> figure out a way to do it as well, please, let me know.
I see. This is a new version that would also work with org attachment
links. I haven't tested it much and the function is a bit tricky, but I
think it works fine:
#+begin_src emacs-lisp
(defun my-org-rename-link-file-at-point ()
(interactive)
(let* ((curr-dir (if (equal (org-element-property :type (org-element-context)) "attachment")
(concat (abbreviate-file-name (org-attach-dir)) "/")
(abbreviate-file-name default-directory)))
(current-path (if (equal (org-element-property :type (org-element-context)) "attachment")
(concat curr-dir (org-element-property :path (org-element-context)))
(org-element-property :path (org-element-context))))
(new-path (read-file-name "Rename file at point to: " current-path)))
(rename-file current-path new-path)
(message (concat "moved to: " new-path))
(if (directory-name-p new-path)
(setq new-path (concat new-path (file-name-nondirectory current-path)))
(setq new-path new-path))
(if (equal (org-element-property :type (org-element-context)) "attachment")
(my-org-replace-link-file (file-name-nondirectory current-path)
(replace-regexp-in-string
curr-dir "" new-path))
(my-org-replace-link-file current-path
(replace-regexp-in-string
curr-dir "" new-path)))))
(defun my-org-replace-link-file (from to)
(save-excursion
(goto-char (point-min))
(while (re-search-forward org-bracket-link-regexp nil t)
(cond ((string-match-p (concat "attachment:" from) (match-string 1))
(replace-match (concat "[[attachment:" to "]]")))
((string-match-p from (match-string 1))
(replace-match (concat "[[file:" to "]]")))))))
#+end_src
Best regards,
Juan Manuel
[-- Attachment #1: Type: text/plain, Size: 1779 bytes --] On 19 March 2022 11:25, Juan Manuel Macías <maciaschain@posteo.net> wrote: > #+begin_src emacs-lisp > (defun my-org-rename-link-file-at-point () > (interactive) > (let* ((curr-dir (if (equal (org-element-property :type (org-element-context)) "attachment") > (concat (abbreviate-file-name (org-attach-dir)) "/") > (abbreviate-file-name default-directory))) > (current-path (if (equal (org-element-property :type (org-element-context)) "attachment") > (concat curr-dir (org-element-property :path (org-element-context))) > (org-element-property :path (org-element-context)))) > (new-path (read-file-name "Rename file at point to: " current-path))) > (rename-file current-path new-path) > (message (concat "moved to: " new-path)) > (if (directory-name-p new-path) > (setq new-path (concat new-path (file-name-nondirectory current-path))) > (setq new-path new-path)) > (if (equal (org-element-property :type (org-element-context)) "attachment") > (my-org-replace-link-file (file-name-nondirectory current-path) > (replace-regexp-in-string > curr-dir "" new-path)) > (my-org-replace-link-file current-path > (replace-regexp-in-string > curr-dir "" new-path))))) > > (defun my-org-replace-link-file (from to) > (save-excursion > (goto-char (point-min)) > (while (re-search-forward org-bracket-link-regexp nil t) > (cond ((string-match-p (concat "attachment:" from) (match-string 1)) > (replace-match (concat "[[attachment:" to "]]"))) > ((string-match-p from (match-string 1)) > (replace-match (concat "[[file:" to "]]"))))))) > #+end_src Just a couple of fixes and it seems to be working fine. [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: org-rename-link.patch --] [-- Type: text/x-patch, Size: 1012 bytes --] diff -u a/org-rename-link.el b/org-rename-link.el --- a/org-rename-link.el 2022-03-22 12:08:45.790727092 -0300 +++ b/org-rename-link.el 2022-03-22 12:25:31.500218923 -0300 @@ -23,8 +23,11 @@ (defun my-org-replace-link-file (from to) (save-excursion (goto-char (point-min)) - (while (re-search-forward org-bracket-link-regexp nil t) - (cond ((string-match-p (concat "attachment:" from) (match-string 1)) - (replace-match (concat "[[attachment:" to "]]"))) - ((string-match-p from (match-string 1)) - (replace-match (concat "[[file:" to "]]"))))))) + (while (re-search-forward org-link-bracket-re nil t) + (replace-match + (cond + ((string-match-p (format "^attachment:%s\\'" from) (match-string 1)) + (format "attachment:%s" (file-name-nondirectory to))) + ((string-match-p (format "^file.*:%s\\'" from) (match-string 1)) + (format "file:%s" to))) + nil nil nil 1)))) Diff finished. Tue Mar 22 12:26:56 2022 [-- Attachment #3: Type: text/plain, Size: 439 bytes --] All this patch does is to remove the directory name from the =attachment:file.ext= -- given that the path is calculated by org-attach --, and use the group 1 of the match string (as well as updating the use of an obsolete variable), which corresponds to the actual link portion, leaving the description unchanged. Cordially, -- João Pedro de A. Paula IT undergraduate at Universidade Federal do Rio Grande do Norte (UFRN)