2

I am having a problem writing a script for mass renaming of files in subdirectories.

I have a folder with multiple subfolders, and those subfolders have multiple files that I need to rename.

This is the where I got so far:

for file in $(find -name "*.report")
do
  mv "$file" "LPP_${file/LP_/}"
done

So as you can see, I need to replace the 'LP_' string in the filename with the 'LPP_'.

This is not working because of the path to the file - the strings retrieved from the find command are only file names, and don't include the path. To include the path, I am trying something like this:

for file in $(find -name "*.report")
do
  echo "$file" 
  echo "${RELPATH/\$\//}/${file/LP_/LPP_}"
done

But the RELPATH variable is prefixing a '/' character, so the mv command is complaining that it cannot move the file to /./subfolder1/LPP_filename.report

Can someone tell me what am I doing wrong, is there a better way of doing it, and explain why is there an extra '/' character in te RELPATH variable and how to remove it?

Thank you all in advance!

  • Just a heads-up: that for loop won't work in files/folders with names that contain spaces! You should use something like what steeldriver suggests in his answer. – user180409 Nov 14 '14 at 20:19
  • well, I might consider to start using python for stuff like this, but can you first point me to some materials on how to set it up? I can use windows cmd, anything. I am looking for something that I will use in future, i thought git bash is good enough to start with. – sskular Nov 15 '14 at 11:07
2

I don't really understand your issue (find should return the full path), however I suggest a different approach, perhaps something like

find -name '*.report' -execdir bash -c 'echo mv "$0" "${0/LP_/LPP_}"' {} \;

By passing the find result {} as a shell positional parameter $0 to a subordinate bash -c command, we can work around the fact that we can't do mv {} ${{}/LP_/LPP_} directly. The use of -execdir instead of the more common -exec ensures that the substitution happens only on the filename portion, in case any of the paths happens to contain the string LP_

The echo is just so you can try it out and check that the renaming looks correct - you will need to remove it to allow actual renaming.

  • When I run this in bash, it says: find: invalid predicate `-execdir' when I run only find command, it can't find any file, and there are files in there, in subdirectories. I am using git bash installed on my windows machine. – sskular Nov 15 '14 at 11:03
  • Thanks for the hint on the find command, it must have been too late for me to think properly, don't know how I missed it. Here is the code with which I managed to pull it off: for file in $(find -name "*.report") do mv "$file" "${file/LP_/LPP_}" done If you could provide some more details around your answer, and maybe include this approach in the answer as well and I will then mark your answer as the best answer. Thanks for the help!! – sskular Nov 15 '14 at 11:25
  • @sskular there are 2 issues with the code in your comment above: (1) it will break if any of the paths contains a space (word splitting); and (2) it will try to rename the first instance of LP_ anywhere in the path so will also break if any of the subdirectory names happens to include the string LP_. If it works for your case that's fine - but it's not a robust solution in general. – steeldriver Nov 15 '14 at 13:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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