Copy Folder with subfolder + change part of every foldername

Hi there,

if someone could help me out here, I would be very happy :slight_smile:

Starting situation:

For new customers, I am currently copying a template project folder in which also always the same source files are stored.
but the renaming refers only to the folders, not the files. The files are only the reason why the folders should be copied and not created.

All subfolders should contain the name of the customer in addition to the specific folder names.

Folder structure is as follows:

yymmdd-XXX(individual customer name)


and some Subfolders again have subfolders with the same structure


All subfolders should contain besides the actual name, also a variable (customer name).

If someone can help me here I would be incredibly grateful. I'm a little lost at the moment :slight_smile:
Thanks to you in advance!

This will duplicate and rename the template folder (whose path must be set in the green action) and rename its subfolders. I'm not sure how to go beyond one subfolder level, but I have a feeling @Sleepy might, having seen a similar shell script he offered up.

Template — Duplicate and Name.kmmacros (22 KB)

Macro screenshot

1 Like

Thank you so much Neil!

If you fancy a recursive shell script version, this'll replace "XXX" with an entered customer name for all files and folders starting from within a folder of your choosing.

Recursive Rename.kmmacros (3.1 KB)


Nice one @Nige_S

Does that require an external script? Tried it one a folder titled "Folder - XXX" and got:

Execute a Shell Script failed with script error: zmv:239: no matches found: **/(*-)XXX(*)(odon). Ma
cro “Recursive Rename” cancelled (while executing Execute Shell Script).

Assuming it does work, is there a version of that script to append (rather than replace) text recursively?

1 Like

I'll admit, zmv is new to me -- I stumbled across it last night and thought of this thread!

It's a function in the z shell, but isn't loaded by default -- hence the first two lines that designate the shell to use and then load the function.

A quick test (that I hadn't tried earlier) shows that it works on everything within the target directory, but not on the target itself (post above updated to include that), so I'm guessing you had a single directory to rename that you chose in the script:

Folder-XXX -- will error

To Rename                         To Rename
    Folder-XXX          ->          Folder-John Smith
        File-XXX                        File-John Smith


To Rename-XXX                   To Rename-XXX
    Folder-XXX          ->          Folder-John Smith
        File-XXX                        File-John Smith

Also note that the pattern match in zmv has no space between - and X, as per OP's naming convention.

Appending is as simple as changing the last line to:
zmv '(**/)(*)' '$1$2$KMVAR_customerName'
but do note that will append to everything, so myFile.txt would become myFile.txt.John Smith, which probably isn't the intended behaviour! I don't (yet!) know how to treat files and folder differently or how to make .extension "optional" in the pattern match

Clever stuff. I don't think @Stefan_Loe wanted the files renaming at all, as there was no mention of it in his request. Is there a way to target the folders only? There must be a way to rename the parent folder too, surely.

1 Like

Shell globbing always start in the directory, eg ls * lists contents and not the directory itself. There's almost certainly (because Unix!) an option to change that behaviour to include the . file (current directory) but I'd worry about also targeting other hidden files like .DSStore.

find is similar. I guess you could start one folder above the chosen folder, but it's probably just easier to change it in a separate step if it needs doing.

For the files, I don't think they'll be renamed because I don't think they'll have XXX in their names (and if they did I'd expect them to need to be renamed!).

But find lets us control what gets changed, and also makes it easier to pump in variables from KM. So here's a variant using find which is slower (unlike shell globbing it has to spawn a process for every file changed) but certainly more user friendly.

Recursive Rename using 'find'.kmmacros (10.1 KB)


On your KM-native macro:

I did a thing a couple of weeks back showing that KM did recursion -- this could be the ideal example of practical use!

1 Like

Yeah that makes sense.

The append version interested me most and that one does rename the files.

Mmmm that was satisfying to use. Very nice work.

Just had a quick read and can't quite fathom the recursion logic. I'll have to mull it over... I think this is the first time I've seen it done in KM! :trophy:

1 Like

TBH, I was running out "clean dialog" options -- because there are no proper radio buttons you'd need to put "Change", "Prepend" and "Append" in as checkboxes. Hmmm, perhaps you could do variables for each and, if blank, that operation doesn't happen.

And I assume by "Append" you mean "add between end of name and beginning of extension (if any)"? So myFile -> myFileExtra and myFile.txt ->myFileExtra.txt?

Pseudo-code for the renaming example, in case something concrete helps:

on myRename(aFolder)
    set Local_collection to contents of aFolder
    for eachItem in Local_collection do
        if eachItem is a directory then
            do renaming on eachItem
        end if
    end for
    do renaming on aFolder
end myRenaming

So if you have


...and you call myRename(dir1), the routine would look in folder dir1 and see subdir2. That's a folder, so myRename(subdir2) would be called and would see subdir3. That's also a folder, so myRename(subdir3) is called.

At this point you have


all running.

Everything in subdir3 is a file, matching the else of the if, so is renamed. Finally subdir3 is renamed and myRename(subdir3) exits, returning "control" to myRename(subdir2). So you know have


myRename(subdir2) then recurses any other folder in it's collection (none in this case) as above, renames all files, renames subdir2, and exits. "Control" is returned to myRename(dir1),... etc.

"See a directory, dig down a level. See a file, process. Nothing left in there to process? Rename self, go back up a level, continue."

The two tricks here are:
a) Dig down first! That's what the -d in the shell script find command is there for. Otherwise you end up renaming any "child" directories before you process their contents and the previous paths to those contents are now invalid.
b) Have a "stop and return" condition in the function -- in our case it's "everything in Local_collection has been processed" -- else you'll get runaway recursion :frowning: Luckily KM has a limit on the number of macro instances that can run at once, so you won't lock your machine up. (Unluckily that same limit will stop us from going more than ~24 folders deep -- each recursion seems to count as two "normal" instances -- unless you change a hidden preference from the default of "50".)


Crikey. I'm pretty sure I saw you say you're quite new to KM, but you're clearly well versed in this kind of thing. Colour me impressed!

Exactly. There's no practical difference if you're copying a template as per the OP, as you could easily save the starting configuration with "XXX" or similar, but I can imagine making versions of existing projects would be easier with the append function.

1 Like

Trial's just run out on my work machine, which is why I haven't tried to make an "append" or "KM native" version yet. Plus, of course, I'm supposed to be working :wink:

Mind you, software evaluation is part of the job...

Still trying to decide whether to buy -- KM is brilliant, but I can't find much in what I do where it will save more work time than it'll cost in development. Regexed typed string triggers may just tip the balance...

1 Like

Thank you guys - thats amazing! As a beginner it is hard to understand everything, but i am so happy to have that macro and i will going on learning Maestro :wink:
All best to you!

1 Like

Here's a simple, recursive, "append to files and not to folders" KM-native macro pair which should be easier to follow. (Why files and not folders? Simply so I could play around with the filename filters!)

Basic Recursive Append Macros.kmmacros (7.6 KB)


The "master" just collects the details -- start folder, text to add -- and passes those to the subroutine. The sub starts at given folder and works on the contents -- if an item is a directory then sub calls itself, passing the path to the that item and the text to add, and if it's a file it renames it.

Note that, like most "append" schemes, you can get "unexpected" results on multi-dotted files... my.file.txt and myfile.tar.gz should "obviously" have text appended between file and ., but what's obvious to us isn't to a computer.

And I can't help but think there's a way to do the file type test in the if statement rather than using yet more variables, if only I knew more about KM...

1 Like