Issue
I have tried to rename some files which has 2 extensions in a folder which also has multiple folders. For example :
"./3/test/us.bak.alt"
"./3/test/ca.bak.alt"
"./3/test/me.bak.alt"
"./3/test/mi.bak.alt"
"./3/new.BAK.alt"
"./3/alt.bak.alt"
These should be renamed to *.BAK (so the .alt at the end should be deleted), but only if the .BAK file does not already exist. And I tried this code :
find -name "*.alt" | sed 's/\(.*\)\.alt/mv "&" \1.BAK"/'
the oupt should be like this:
"./3/test/us.BAK"
"./3/test/ca.BAK"
"./3/test/me.BAK"
"./3/test/mi.BAK"
"./3/new.BAK"
"./3/alt.BAK"
What I'm missing here?
Solution
You are missing several things:
- You should limit the find search to files.
- Your
sed
script does not replace.bak.alt
by.BAK
, it replaces.alt
by.BAK
. - There is a missing double quote in your
sed
script. - You should limit the
sed
search to the end of the file names. - You have a
new.BAK.alt
file in your input list. - You have an empty string
""
in your input list. - You have a
./3/test/us.bak.alt
in your desired output list, which apparently contradicts your specification.
Let's ignore the 3 last issues, they are probably typos. To fix the 4 others try:
find . -type f -name "*.bak.alt" | sed 's/\(.*\)\.bak\.alt$/mv "&" "\1.BAK"/'
If the fifth issue is a real one and you also have *.BAK.alt
files that you want to rename as *.BAK
:
find . -type f \( -name "*.bak.alt" -o -name "*.BAK.alt" \) |
sed -E 's/(.*)\.(bak|BAK)\.alt$/mv "&" "\1.BAK"/'
With one or the other, when you will be satisfied with the printed output, you can execute them all with a very small change if you use GNU sed:
find . -type f -name "*.bak.alt" | sed 's/\(.*\)\.bak\.alt$/mv "&" "\1.BAK"/;e'
or:
find . -type f \( -name "*.bak.alt" -o -name "*.BAK.alt" \) |
sed -E 's/(.*)\.(bak|BAK)\.alt$/mv "&" "\1.BAK"/;e'
(the e
sed command executes the content of the pattern space).
Answered By - Renaud Pacalet Answer Checked By - Robin (WPSolving Admin)