I have recently discovered this technique for renaming files using zsh:

autoload zmv
zmv '(*).JPG' '$1.jpg'

which I can also write as:

autoload zmv; zmv '(*).JPG' '$1.jpg'

This works as advertised and I can use it to change the Upper Case JPG extension to lower case.

However, I would like to run this as a one-liner from my usual BASH shell. When I try to call it as follows:

zsh -c "autoload zmv; zmv -f '(*).JPG' '$1.jpg'"

or as:

echo 'autoload zmv; zmv -f "(*).JPG" "$1.jpg"' | zsh -i

I get something like the following message

zmv: error(s) in substitution:
….JPG and ….JPG both map to .jpg

This suggests to me that that zsh is treating the file names case-insensitively, but that does not appear to be the case when run the first way.

Obviously, I don’t know what I’m doing here. I have also tried reversing the single and double quotes in case shell expansion is getting in the way.

How can I run this command as a one-liner from bash?

up vote 4 down vote accepted

In:

zsh -c "autoload zmv; zmv -f '(*).JPG' '$1.jpg'"

The $1 is between double quotes, so expanded by your shell (bash), most probably to the empty string so zsh ends up interpreting:

autoload zmv; zmv -f '(*).JPG' '.jpg'

Use:

zsh -c "autoload zmv && zmv '(*).JPG' '\$1.jpg'"

Where the backslash quotes the $ for bash to remove its special meaning inside double quotes.

You can also do:

zsh -c "autoload zmv && zmv '(*).(#i)jpg' '\$1.jpg'"

Where (#i) is to turn on case-insensitive matching so it also renames the .Jpg, .JPg, .jpG... files.

You could also make it a function:

fix_ext_case() {
  EXT=$1 zsh -c "autoload zmv && zmv \"(*).(#i)\$EXT\" '\$1.\$EXT'"
}

Or with a different combination of quotes:

fix_ext_case() {
  EXT=$1 zsh -c 'autoload zmv && zmv "(*).(#i)$EXT" "\$1.\$EXT"'
}

To be used as:

fix_ext_case jpg

or

fix_ext_case png

(or fix_ext_case JPG if you want to convert to upper-case).

  • Excellent. The `` did the trick. Thanks also for your additional information. – Manngo Oct 27 '17 at 11:55

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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