I'm trying to write a zsh script on MacOS Big Sur that will recursively rename some files and directories that have special characters I don't want. Been at it for days and every time I think I have it cracked, I get hit with a new problem. It's basically done, except that when I run the find command in dry run mode:

find . -d -type f -execdir rename -n -X ${=CHARACTER_SUBSTITUTIONS} {} +

I get the correct list of files in my test folder:

'untitled file3 [].txt' would be renamed to 'untitled file3 --.txt'
'untitled file2. [].txt' would be renamed to 'untitled file2. --.txt'

But when I run it for realsies, it can't find them anymore:

find . -d -type f -execdir rename -X ${=CHARACTER_SUBSTITUTIONS} {} +


Can't rename 'untitled file3 [].txt' to 'untitled file3 --.txt': No such file or directory
Can't rename 'untitled file2. [].txt' to 'untitled file2. --.txt': No such file or directory

Banging my head against a wall. Any help would be greatly appreciated.

In case it's relevant, CHARACTER_SUBSTITUTIONS is just a long list of the subs I want to make.

-S [ - -S ] - -S + - -S # - -S % - -S { - -S } - -S \ - -S < - -S > - -S * - -S ? - -S $ - -S ! - -S : - -S @ - -S ` - -S | - -S ' - -S " - -S & - -S  - -S = -

MacOS Big Sur
rename v1.601 (one of the Perl-based variants)

  • The ${=...} expansion would happen before find is invoked.
    – Kusalananda
    May 20, 2021 at 15:16

1 Answer 1


Since you're using Zsh, I would just use zmv for this instead of find:

% autoload -Uz zmv
% zmv -n '(**/)(*)(#q.)' '$1${2//[^. [:IDENT:]]/-}'  # -n: no execute
mv -- 'untitled file2 [].txt' 'untitled file2 --.txt'
mv -- 'untitled file3 [].txt' 'untitled file3 --.txt'
% zmv -v '(**/)(*)(#q.)' '$1${2//[^. [:IDENT:]]/-}'  # -v: verbose
mv -- 'untitled file2 [].txt' 'untitled file2 --.txt'
mv -- 'untitled file3 [].txt' 'untitled file3 --.txt'

[^. [:IDENT:]] matches anything that's not a dot, space or valid part of a shell identifier. (#q.) is to restrict the rename to regular files like your -type f.

For more info:

  • OMG you did it. Thank you so much! Not gonna lie, throwing out everything I worked on and going in a different direction is tough -- but I can't argue with results. :) May 20, 2021 at 17:47
  • Getting my head around zmv was no small task. So I just want to add some things for anyone reading this later. 1. The best source I found for understanding how to use it is actually the source code itself. Specifically, the large comment block at the top of this page: opensource.apple.com/source/zsh/zsh-30/zsh/Functions/Misc/… 2. zmv processes depth-first by default. This is important so the files get renamed before their containing folders do. I tested on a large, sprawling folder hierarchy, and it all worked. 180 changes to both files and folders. May 20, 2021 at 17:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .