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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.