Hi Daniel Shahaf, Thank you very much. *Thanks and Best Regards,Ahmad Ismail* On Tue, Nov 17, 2020 at 1:53 AM Daniel Shahaf wrote: > Ahmad Ismail wrote on Sat, 14 Nov 2020 03:45 +0600: > > Hi All, > > > > I have the following functions that rename files from camel to sort of > > kebab case. > > > > function ctokfiles() { > > # Transform [Capital][Capital][Small] to [Capital]-[Capital][Small] > > zmv -Q '(**/)(*[A-Z][A-Z][a-z]*)(.adoc|.txt)' > '$1${2//(#b)([A-Z])([A-Z][a-z])/$match[1]-$match[2]}$3' > > > > # Put - Between [Small][Capital] > > zmv -Q '(**/)(*[a-z][A-Z]*)(.adoc|.txt)' > '$1${2//(#b)([a-z])([A-Z])/$match[1]-$match[2]}$3' > > > > # Change [Capital][Small] to Lovercase > > zmv -Q '(**/)(*[A-Z][a-z]*)(.adoc|.txt)' > '$1${2//(#m)[A-Z][a-z]/${(L)MATCH}}$3' > > } > > > > So, IF the input name is "ThisIsMyOCDTalking", it becomes > > "this-is-my-OCD-talking". > > > > Now I want to rename directories, adoc & txt files only. For > directories, I > > think I have to use > > > > zmv -Q '(**/)(*[A-Z][A-Z][a-z]*)(/)' > > > > How to make a function that will work on adoc, txt and directories. I > tried > > (/|.adoc|.txt), apparently not working. > > > > Consider how in «*foo*(bar)», the «foo» are matched against the > filename but the «bar» are parsed as glob qualifiers. You can't just > juxtapose them within the same set of parentheses; they're apples and > oranges. > > I don't see a good solution for "Everything in «**/*» that's > a directory or named *.foo or *.bar". I'd consider find(1) for this. > > > One more thing, is there any way I can reduce the steps in this > functions. > > As a rule, I wouldn't recommend reducing steps in functions in the > first place, unless you're coding for sport rather than robustness — in > which case, I'd probably opt for Perl: > > % print -rNC1 -- *.(adoc|txt)(N) *(/N) | rename -0 -n '$_ = join "-", map > { /[a-z]/ ? lc : $_ } split /(?<=[a-z])(?=[A-Z])|(?=[A-Z][a-z])/' > rename(ThisIsMyOCDTalking.adoc, this-is-my-OCD-talking.adoc) > % > > The main algorithmic difference is splitting the filename into an array > on zero-width lookaround matches. I don't think there's a native zsh > equivalent of this. > > Note that changing «print -rNC1» to «ls» would introduce two separate bugs. > > I'm not sure how to extend this to nested hierarchies, given the > possibility of foo/bar where both foo and bar have to be changed. > Perhaps with «rename -d» and ensuring the input is sorted children > before their parents. > > Cheers, > > Daniel >