0

I have a large number of files in a directory structure I want to rename.

The file names are in this format:
"aaaaaa-bbbbbb_cccccc-ddddd_eeeee-fffff-ggggg-hhhhh.psd"

I want them in this format:
"Aaaaaa-Bbbbbb_Cccccc-Ddddd_Eeeee-Fffff-Ggggg-Hhhhh.psd

A single find and sed routine should transform them into the correct format:

find . -name "*psd" -exec sh -c "echo 'cp '{} `echo {} | sed 's/\([_-][a-z]\)\([A-Z]*\)/\2\U\1/g'`" \;

But it doesn't work:

input:

Assisted-or-Auto/Abstract-Render/assisted-or-auto_abstract-render_tiny-bubbles3.psd

output:

cp ./Assisted-or-Auto/Abstract-Render/assisted-or-auto_abstract-render_tiny-bubbles3.psd ./Assisted-or-Auto/Abstract-Render/assisted-or-auto_abstract-render_tiny-bubbles3.psd

The sed routine works if I remove the backtick and insert a semi-colon.

find . -name "*bubbles3.psd" -exec sh -c "echo 'cp '{} ; echo {} | sed 's/\([_-][a-z]\([A-Z]*\)/\2\U\1/g'" \;

cp ./Assisted-or-Auto/Abstract-Render/assisted-or-auto_abstract-render_tiny-bubbles3.psd
./Assisted-Or-Auto/Abstract-Render/assisted-Or-Auto_Abstract-Render_Tiny-Bubbles3.psd

So, for some reason backtick is not do what it should be doing. Any ideas on how I can resolve this issue? fyi replacing backticks with the " $(cmd) " notation has the same effect

Thanks

C0ppert0p
  • 634
  • 2
  • 7
  • 23

5 Answers5

2

Most likely, the shell is interpreting the command inside the backticks first (even before running find). However, "{}" won't have any special meaning until after find runs. Try creating a shell function or bash script for your command instead of writing it inline. That should let you do more complex things without worrying about problems with shell escapes.

bta
  • 43,959
  • 6
  • 69
  • 99
0

try

sed 's/\([/_-][a-z]\)\([A-Z]*\)/\2\U\1/g'

i.e.

echo $'./Assisted-or-Auto/Abstract-Render/assisted-or-auto_abstract-render_tiny-bubbles3.psd' \
| sed 's/\([/_-][a-z]\)\([A-Z]*\)/\2\U\1/g'

output

./Assisted-Or-Auto/Abstract-Render/Assisted-Or-Auto_Abstract-Render_Tiny-Bubbles3.psd

I only added the '/' to match the initial lowercase word-part (and my sed said mismatched \( .. \) so I added them 1 in in the logical place.

I hope this helps.

shellter
  • 36,525
  • 7
  • 83
  • 90
0

slight variation

$ input=Assisted-or-Auto/Abstract-Render/assisted-or-auto_abstract-render_tiny-bubbles3.psd
$ sed 's!\(/\|-\|_\)[a-z]!\U&!g' <<< "$input"
Assisted-Or-Auto/Abstract-Render/Assisted-Or-Auto_Abstract-Render_Tiny-Bubbles3.psd

can be made a little cleaner with GNU sed

$ sed 's!(/|-|_)[a-z]!\U&!g' <<< "$input"
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
0

Avoid backticks, as that means you're asking for escaping issues.

As was already pointed out, it is likely that the backticks take effect before the invocation of find.

Use $(), which can be nested without much escaping trouble and then escape the $ in $(command) so that it will survive the invocation and get passed to find. From that point on (assuming that find uses a shell - e.g. $SHELL - to execute your command) things will work fine.

0xC0000022L
  • 20,597
  • 9
  • 86
  • 152
0

This might work for you:

find . -name "*bubbles3.psd" | 
sed 'h;s/\(^\|[/_-]\)./\U&/g;H;g;s/^/cp -v /;s/\n/ /' |
bash

If you want to see the cp command prior to execution, just leave off the last pipe | bash

potong
  • 55,640
  • 6
  • 51
  • 83