Reputation: 702
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
Upvotes: 0
Views: 1575
Reputation: 58430
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
Upvotes: 0
Reputation: 21289
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.
Upvotes: 0
Reputation: 246837
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"
Upvotes: 0
Reputation: 45057
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.
Upvotes: 2
Reputation: 37288
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.
Upvotes: 0