Hello
I would like to rename all files in a database with a prefix of “YYYYMMDD” to a prefix of “YYYY-MM-DD”.
Any help would be much appreciated.
–Jonahtan
Hello
I would like to rename all files in a database with a prefix of “YYYYMMDD” to a prefix of “YYYY-MM-DD”.
Any help would be much appreciated.
–Jonahtan
This works on a selection of files that begin with a string of 8 numbers (regardless if it’s actually yyyymmdd). It will treat those 8 numbers as yyyy-mm-dd (or yyyy-dd-mm, depending on how you view them)…
PS: There is no “undo” for this operation. Test this out on some files and groups first.
Great - thanks so much.
Is there anyway to do this on all files in a database without having to go in to all the nested groups and select files manually?
No.
You need to make a selection of some sort, and I certainly would not advocate doing it “on all the files in a database”… unless there were very few files. You shouldn’t attempt to do such sweeping changes unless you are working with a very strictly conforming dataset.
You could create a smart group (see Data > New > Smart Group) like this…
Given Jim’s important caution about over-automating anything that changes data, you can at least:
The fmap for applying some other function recursively could be written in JavaScript for Automation (and specialised for DEVONthink) as:
Javascript for Automation
// A generic function which applies some other function
// to a DT Item, and also to each of its descendants,
// returning a tree structure in which each node contains
// the results of that function application.
// fmapPureDT :: (DTItem -> a) -> DTItem -> Tree a
const fmapPureDT = (f, item) => {
const go = x => Node(
f(x),
x.children()
.map(go)
);
return go(item);
};
or in Applescript as:
-- A generic function which applies some other function
-- to a DT Item, and also to each of its descendants,
-- returning a tree structure in which each node contains
-- the results of that function application.
-- fmapPureDT :: (DTItem -> a) -> DTItem -> Tree a
on fmapPureDT(fn, dtItem)
using terms from application "DEVONthink Pro"
script go
property f : mReturn(fn)'s |λ|
on |λ|(x)
Node(f(x), my map(go, children of x))
end |λ|
end script
go's |λ|(dtItem)
end using terms from
end fmapPureDT
A full example which just adds a tag to the selected item, and to all of its descendants, might be (first in JXA and then in Applescript):
Javascript for Automation
(() => {
'use strict';
// valueOrTransform :: DTItem -> IO Dict
function valueOrTransform(item) {
// A small change, like adding a tag
item.tags = item.tags().concat('toRead');
// and a returned report.
return {
title: item.name(),
tags: item.tags()
};
}
// MAIN ---------------------------------------------------
const main = () => {
const
dt = Application('DevonThink Pro'),
seln = dt.selection();
// Apply fmapPureDT to the first selected item,
// and let it recurse through all descendants.
return seln.length > 0 ? (
fmapPureDT(valueOrTransform, seln[0])
) : [];
};
// A generic function which applies some other function
// to a DT Item, and also to each of its descendants,
// returning a tree structure in which each node contains
// the results of that function application.
// fmapPureDT :: (DTItem -> a) -> DTItem -> Tree a
const fmapPureDT = (f, item) => {
const go = x => Node(
f(x),
x.children()
.map(go)
);
return go(item);
};
// Node :: a -> [Tree a] -> Tree a
const Node = (v, xs) => ({
type: 'Node',
root: v,
nest: xs || []
});
// MAIN ---
return main();
})();
Applescript
-- valueOrTransform :: DTItem -> IO Dict
on valueOrTransform(x)
using terms from application "DEVONthink Pro"
-- A small change, like adding a tag
set tags of x to (tags of x) & "toRead"
-- and a returned report.
{title:name of x, tags:tags of x}
end using terms from
end valueOrTransform
on run
tell application "DEVONthink Pro"
-- Apply a function (thru fmapPureDT) to the first
-- selected item, and let fmapPureDT recurse
-- with it through all descendants.
set seln to selection
if length of seln > 0 then
my fmapPureDT(valueOrTransform, item 1 of seln)
else
seln
end if
end tell
end run
-- A generic function which applies some other function
-- to a DT Item, and also to each of its descendants,
-- returning a tree structure in which each node contains
-- the results of that function application.
-- fmapPureDT :: (DTItem -> a) -> DTItem -> Tree a
on fmapPureDT(fn, dtItem)
using terms from application "DEVONthink Pro"
script go
property f : mReturn(fn)'s |λ|
on |λ|(x)
Node(f(x), my map(go, children of x))
end |λ|
end script
go's |λ|(dtItem)
end using terms from
end fmapPureDT
-- Node :: a -> [Tree a] -> Tree a
on Node(v, xs)
{type:"Node", root:v, nest:xs}
end Node
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
tell mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, i, xs)
end repeat
return lst
end tell
end map
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
if class of f is script then
f
else
script
property |λ| : f
end script
end if
end mReturn
I have been using this - is there anyway to make a menu item (or keyboard shortcut) to do this without having to fill in the source and destination patterns each time?
Thanks
Hi - this RegEx seems to have stopped working with DT3 - I get the following error:
“sed: 1: “s/b([0-9]{2})([0-9]{2}) …”: \4 not defined in the RE”
Any suggestions would be very gratefully received as I use this frequently as I come across groups with old files in.
Thanks
I fixed it - it was the “b” and “[/b]” not sure what they were doing there.
My working regex:
([0-9]{4})([0-9]{2})([0-9]{2})(.*)
replace with: \1-\2-\3\4
Interesting. That was a code to embolden that phrase. Not sure what happened on the forum post.