I want to be able to replace the occurrences of one string with another in the file contents and filenames of all files within a directory minus the ".git" directory. I have the following code, which is good for changing the filenames but doesn't replace strings inside the files. What am I doing wrong?
#!/bin/bash
# Replace occurances in files, lowercase
lower1=$(echo $1 | tr '[:upper:]' '[:lower:]')
lower2=$(echo $2 | tr '[:upper:]' '[:lower:]')
echo "Replacing $lower1 with $lower2..."
find . -type f \! -iregex '.\|./.git' -exec perl -i -pe 's/$lower1/$lower2/g' {} \;
# Replace all other occurances in files to capitalised
upper2=$(echo ${2:0:1} | tr '[:lower:]' '[:upper:]')${2:1}
echo "Replacing all $1 with $upper2..."
find . -type f \! -iregex '.\|./.git' -exec perl -i -pe 's/$1/$upper2/gi' {} \;
# Replace filenames. Use "bash -c" to pass files as arguments to mv command.
# This worked
find . -name "*$lower1*" -exec bash -c 'mv "$1" "${1/$2/$3}"' -- {} $lower1 $lower2 \;
I did try sed, but that wasn't allowing case insensitivity.
I am testing this on OSX Mountain Lion if that makes a difference, though I do want this to work on Linux as well. I'm away from my Linux machine at the moment.
Just use
File::Find
The following code will edit an entire directory tree, so I'd be careful how I used it. Perhaps some testing first? :)
This script accepts two strings as arguments, and then replaces all occurances of $string1 with $string2. For perfect lowercase matches, it will replace with a lowercase $string2, but for all other matches it will replace with uppercase $string2.
Currently, it will just do lowercase for file renames.
If you are doing a lot of file renames, you should check for accidental removal of intermediate results.
mmv
does this admirably.+
is a useful performance boost forfind
.Here is the solution I managed to come up with. Thanks to all that helped me come to it: