Search code examples
linuxshell

replacing file name and content : shell script


I have written the code for replacing content but quite confused with replacing file name, both in the same script. I want my script to run this way:

suppose I give input : ./myscript.sh abc xyz

abc is my string to be replaced 
xyz is the string to replace with

If some directory or any subdirectory or file in it has name abc, that should also change to xyz.

Here is my code:

filepath="/misc/home3/testing/fol1"
for file in $(grep -lR $1 $filepath)
do
sed  -i "s/$1/$2/g" $file
echo "Modified: " $file
done

Now How should I code to replace the filename as well.

I tried:

if( *$1*==$file )
then  
rename $1 $2 $filepath
fi

and

find -iname $filepath -exec mv $1 $2 \;

but any of then is not working correctly. What should I do? Which approach should I take?

Any help would be appreciated. Thanks :)


Solution

  • #!/bin/bash
    dir=$1 str=$2 rep=$3
    while IFS= read -rd '' file; do
        sed  -i "s/$str/$rep/g" -- "$file"
        base=${file##*/} dir=${file%/*}
        [[ $base == *"$str"* ]] && mv "$file" "$dir/${base//$str/$rep}"
    done < <(exec grep -ZFlR "$str" "$dir")
    

    Usage:

    bash script.sh dir string replacement
    

    Note: rename would also rename the directory part.

    • grep -Z makes it produce null-delimited outputs. i.e. it produces output which is composed of filenames in which everything is separated by 0x00.
    • -d '' makes read read input delimited by 0x00; -r prevents backslashes to be interpreted; and IFS= prevents word splitting with IFS.
    • IFS= read -rd '' makes read read input with delimiter of `0
    • base=${file##*/} removes the directory part. It's the same as base=$(basename "$file")
    • dir=${file%/*} removes the file part.
    • [[ $base == *"$str"* ]] checks if the filename has something that could be renamed. && makes the command that follows it execute if the previous returns zero (true) code. Think of it as a single link if statement.
    • "$dir/${base//$str/$rep}" forms the new filename. ${base//$str/$rep} replaces anything in $base that matches value of $str and replace it with value of $rep.