# Batch rename to initial lower case

**URL:** <https://discourse.devontechnologies.com/t/batch-rename-to-initial-lower-case/87490>\
**Category:** Automation\
**Created:** [August 17, 2026, 2:16pm UTC](https://discourse.devontechnologies.com/t/batch-rename-to-initial-lower-case/87490 "2026-08-17T14:16:06Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![brookter](https://discourse.devontechnologies.com/user_avatar/discourse.devontechnologies.com/brookter/32/4458_2.png) [@brookter](https://discourse.devontechnologies.com/u/brookter)\
**Post date:** [August 17, 2026, 2:16pm UTC](https://discourse.devontechnologies.com/t/batch-rename-to-initial-lower-case/87490/1 "2026-08-17T14:16:06Z")

</div>

Hi,

I’d like to rename all my tags to purely lowercase, and I’ve been trying to use Batch Renaming to do it.

The following regex works in BBEdit:

```auto
Input: Translate
Search: ^([A-Z])(.*)
Replace: \l\1\2
Output: translate

```

But it doesn’t work in DT4, where:

 ![Screenshot 2026-08-17 at 15.13.17](https://devontech-discourse.s3.dualstack.us-east-1.amazonaws.com/uploads/original/3X/9/b/9b8a56e82bddccebadc2d3645f3935b6a5b43a3d.png)

results in `\1Translate`.

Is this just one of those features of regex that hasn’t been implemented, or am I doing something wrong.

Is there another way of doing this without using AppleScript?

Thanks!

---

<div class="post-metadata">

**Author:** ![cgrunenberg](https://discourse.devontechnologies.com/user_avatar/discourse.devontechnologies.com/cgrunenberg/32/7172_2.png) [@cgrunenberg](https://discourse.devontechnologies.com/u/cgrunenberg)\
**Post date:** [August 17, 2026, 2:21pm UTC](https://discourse.devontechnologies.com/t/batch-rename-to-initial-lower-case/87490/2 "2026-08-17T14:21:14Z")

</div>

> [@brookter](#):
>
> Is this just one of those features of regex that hasn’t been implemented, or am I doing something wrong.

Regular expressions are only used by the _Scan Name/Text_ actions, all other actions like _Change Name_ are only able to use the numbered results.

The _Script with Input/Output_ action might be a good alternative, there are already scripts for lower and upper case (see `~/Library/Application Scripts/com.devon-technologies.think/Script Output/`)

---

<div class="post-metadata">

**Author:** ![chrillek](https://discourse.devontechnologies.com/user_avatar/discourse.devontechnologies.com/chrillek/32/29340_2.png) [@chrillek](https://discourse.devontechnologies.com/u/chrillek)\
**Post date:** [August 17, 2026, 2:53pm UTC](https://discourse.devontechnologies.com/t/batch-rename-to-initial-lower-case/87490/3 "2026-08-17T14:53:32Z")

</div>

Firstly, your RE is borken, even in BBEdit.  
Example: “MyFunnyTag” will be converted to “myFunnyTag”.  
It’s a serious case of overengineering: If you want to lowercase a string, just do it:  
(.\*) =\> \l\1

Or is that the _intended_ behavior, as in the title of your post? Whereas in the text, you say that you want to rename tags to “purely lowercase”, which is not quite the same as “initial lower case”.

> [@brookter](#):
>
> Is this just one of those features of regex that hasn’t been implemented,

DT uses Apple’s framework for REs. And lowercasing in the replace function is not really standard anyway. I think Perl can do that, but JavaScript (for example) can’t.  
You can find out more about the flags supported by `NSRegularExpression` here:

> **[NSRegularExpression | Apple Developer Documentation](https://developer.apple.com/documentation/foundation/nsregularexpression?language=objc#Flag-Options)**
>
> An immutable representation of a compiled regular expression that you apply to Unicode strings.

though I don’t think that DT has implemented all or even any of them.

So, I’d suggest that you use a tiny script doing what you want, something like

```javascript
(() => {
  const app = Application("DEVONthink");
  const tg = app.currentDatabase.tagsGroup;
  tg.children().forEach(t => t.name = t.name().toLowerCase());
})()

```

Select the database for which you want the tags to be lowercased and run the script.  
No Regular Expressions needed.

If you want only the first character lowercased, change the code in the `forEach` to something like

```javascript
t.name = t.name().charAt(0).toLowerCase() + t.name().substr(1);

```

The code is written in JavaScript/JXA, but I’m confident that the same result can be achieved with AppleScript. There’s an eye-watering example over at Apple’s:

> **[Mac Automation Scripting Guide: Manipulating Text](https://developer.apple.com/library/archive/documentation/LanguagesUtilities/Conceptual/MacAutomationScriptingGuide/ManipulateText.html)**
>
> New document.

that only works for ASCII characters. Oh, well, the good old times …

---

<div class="post-metadata">

**Author:** ![brookter](https://discourse.devontechnologies.com/user_avatar/discourse.devontechnologies.com/brookter/32/4458_2.png) [@brookter](https://discourse.devontechnologies.com/u/brookter)\
**Post date:** [August 17, 2026, 3:31pm UTC](https://discourse.devontechnologies.com/t/batch-rename-to-initial-lower-case/87490/4 "2026-08-17T15:31:49Z")

</div>

I’ll have a look at that action – thanks, Cris!

---

<div class="post-metadata">

**Author:** ![brookter](https://discourse.devontechnologies.com/user_avatar/discourse.devontechnologies.com/brookter/32/4458_2.png) [@brookter](https://discourse.devontechnologies.com/u/brookter)\
**Post date:** [August 17, 2026, 3:35pm UTC](https://discourse.devontechnologies.com/t/batch-rename-to-initial-lower-case/87490/5 "2026-08-17T15:35:39Z")

</div>

> [@chrillek](#):
>
> Or is that the _intended_ behavior, as in the title of your post? Whereas in the text, you say that you want to rename tags to “purely lowercase”, which is not quite the same as “initial lower case”.

Works as intended – I was basically after the principle of what the rename action can do.

I’ve never really used JXA, but perhaps I should start… so thanks for your very helpful examples for another approach, as always!

---

<div class="post-metadata">

**Author:** ![brookter](https://discourse.devontechnologies.com/user_avatar/discourse.devontechnologies.com/brookter/32/4458_2.png) [@brookter](https://discourse.devontechnologies.com/u/brookter)\
**Post date:** [August 17, 2026, 3:52pm UTC](https://discourse.devontechnologies.com/t/batch-rename-to-initial-lower-case/87490/6 "2026-08-17T15:52:50Z")

</div>

@cgrunenberg

I’ve never used the script actions before, so it took a bit of trial and error, but now it works, thank you very much!

 ![Screenshot 2026-08-17 at 16.50.11](https://devontech-discourse.s3.dualstack.us-east-1.amazonaws.com/uploads/original/3X/5/4/54c67bba206f491fc444ec04852d9104b305dc74.png)

@chrillek

While I’ve gone with Cris’s suggestion for simplicity, I really appreciate the time you spent to give such a comprehensive answer – and when I’ve got a bit more free time, I shall look at it, and your other JXA posts in more details to understand more. Thank you again!

---

<div class="post-metadata">

**Author:** ![chrillek](https://discourse.devontechnologies.com/user_avatar/discourse.devontechnologies.com/chrillek/32/29340_2.png) [@chrillek](https://discourse.devontechnologies.com/u/chrillek)\
**Post date:** [August 17, 2026, 4:09pm UTC](https://discourse.devontechnologies.com/t/batch-rename-to-initial-lower-case/87490/7 "2026-08-17T16:09:28Z")

</div>

> [@brookter](#):
>
> While I’ve gone with Cris’s suggestion for simplicity

So, you’re now lowercasing the whole tag, not only the first letter?

---

<div class="post-metadata">

**Author:** ![troejgaard](https://discourse.devontechnologies.com/letter_avatar_proxy/v4/letter/t/58956e/32.png) [@troejgaard](https://discourse.devontechnologies.com/u/troejgaard)\
**Post date:** [August 17, 2026, 4:15pm UTC](https://discourse.devontechnologies.com/t/batch-rename-to-initial-lower-case/87490/8 "2026-08-17T16:15:22Z")

</div>

> [@chrillek](#):
>
> I’d suggest that you use a tiny script doing what you want, something like
> 
> ```auto
> (() => {
> const app = Application("DEVONthink");
> const tg = app.currentDatabase.tagsGroup;
> tg.children().forEach(t => t.name = t.name().toLowerCase());
> })()
> 
> ```

If you have any nested tags this will only affect top level tags. I would suggest using a `whose` filter instead of `database.tagsGroup.children`.

```javascript
// Ordinary tags only:
const tags = database.parents.whose({
	_match: [ObjectSpecifier().tagType, "ordinary tag"]
});

// All tags, including group tags:
const tags = database.parents.whose({
	_not: [
		{_match: [ObjectSpecifier().tagType, "no tag"]}
	]
});

```

You can even get all tags across open databases at once:

```javascript
const tags = app.databases.parents.whose({
	_match: [ObjectSpecifier().tagType, "ordinary tag"]
});

```

That returns an array of arrays, i.e.

```javascript
[
	[app.databases.byId(1).parents.byId(148),
	 app.databases.byId(1).parents.byId(4887),
	 ... ],
	[app.databases.byId(4).parents.byId(838),
	 app.databases.byId(4).parents.byId(975),
	 ... ]
]

```

… so you need to flatten it before proceeding:

```javascript
/* Convert all ordinary tags in open databases to lowercase */
(() => {
	const app = Application("DEVONthink");
	const tags = app.databases.parents.whose({
		_match: [ObjectSpecifier().tagType, "ordinary tag"]
	});
	tags().flat().forEach(t =>
		t.name = t.name().toLowerCase()
	);
})

```

---

<div class="post-metadata">

**Author:** ![brookter](https://discourse.devontechnologies.com/user_avatar/discourse.devontechnologies.com/brookter/32/4458_2.png) [@brookter](https://discourse.devontechnologies.com/u/brookter)\
**Post date:** [August 17, 2026, 4:19pm UTC](https://discourse.devontechnologies.com/t/batch-rename-to-initial-lower-case/87490/9 "2026-08-17T16:19:12Z")

</div>

Yes – as I said, I was mainly interested in whether I could use the regex output (using `\l` and its variants) at all. The specific details of the casing could wait till I’d got the principle sorted, and for the time being, all lowercase will do fine.

---

<div class="post-metadata">

**Author:** ![chrillek](https://discourse.devontechnologies.com/user_avatar/discourse.devontechnologies.com/chrillek/32/29340_2.png) [@chrillek](https://discourse.devontechnologies.com/u/chrillek)\
**Post date:** [August 17, 2026, 4:37pm UTC](https://discourse.devontechnologies.com/t/batch-rename-to-initial-lower-case/87490/10 "2026-08-17T16:37:24Z")

</div>

> [@troejgaard](#):
>
> If you have any nested tags this will only affect top level tags.

Great catch, thanks.
