How do I write a bash script to replace words in files and then rename files?
-
11-10-2019 - |
Question
I have a folder structure, as shown below:
I need to create a bash script that does 4 things:
- It searches all the files in the generic directory and finds the string 'generic' and makes it into 'something'
- As above, but changes "GENERIC" to "SOMETHING"
- As above, but changes "Generic" to "Something"
- Renames any filename that has "generic" in it with "something"
Right now I am doing this process manually by using the search and replace in net beans. I dont know much about bash scripting, but i'm sure this can be done. I'm thinking of something that I would run and it would take "Something" as the input.
Where would I start? what functions should I use? overall guidance would be great. thanks.
I am using Ubuntu 10.5 desktop edition.
Solution
Editing
The substitution part is a sed
script - call it mapname
:
sed -i.bak \
-e 's/generic/something/g' \
-e 's/GENERIC/SOMETHING/g' \
-e 's/Generic/Something/g "$@"
Note that this will change words in comments and strings too, and it will change 'generic' as part of a word rather than just the whole word. If you want just the word, then you use end-word markers around the terms: 's/\<generic\>/something/g'
. The -i.bak
creates backups.
You apply that with:
find . -type f -exec mapname {} +
That creates a command with a list of files and executes it. Clearly, you can, if you prefer, avoid the intermediate mapname
shell/sed script (by writing the sed
script in place of the word mapname
in the find
command). Personally, I prefer to debug things separately.
Renaming
The renaming of the files is best done with the rename
command - of which there are two variants, so you'll need to read your manual. Use one of these two:
find . -name '*generic*' -depth -exec rename generic something {} +
find . -name '*generic*' -depth -exec rename s/generic/something/g {} +
(Thanks to Stephen P for pointing out that I was using a more powerful Perl-based variant of rename
with full Perl regexp capacity, and to Zack and Jefromi for pointing out that the Perl one is found in the real world* too.)
Notes:
- This renames directories.
- It is probably worth keeping the
-depth
in there so that the contents of the directories are renamed before the directories; you could otherwise get messages because you rename the directory and then can't locate the files in it (becausefind
gave you the old name to work with). - The more basic
rename
will move./generic/do_generic.java
to./something/do_generic.java
only. You'd need to run the command more than once to get every component of every file name changed.
* The version of rename
that I use is adapted from code in the 1st Edition of the Camel book.
OTHER TIPS
Steps 1-3 can be done like this:
find .../path/to/generic -type f -print0 |
xargs -0 perl -pi~ -e \
's/\bgeneric\b/something/g;
s/\bGENERIC\b/SOMETHING/g;
s/\bGeneric\b/Something/g;'
I don't understand exactly what you want to happen in step 4 so I can't help with that part.