title: Shell script to rename multiple files and folders
body: <p>I have the following structure</p>
  
  <p>Before</p>
  
  <pre><code>-1.2.3.4
  --1.2.3.4
  ---1.2.3.4--&gt;1.2.3.4.file
  </code></pre>
  
  <p>After</p>
  
  <pre><code>-5.6.7.8
  --5.6.7.8
  ---5.6.7.8--&gt;5.6.7.8.file
  ...
  </code></pre>
  
  <p>I would like to use a bash script that searches files and subdirectories name in a specific directory /home for a specific string, and when it finds the search string (in file or<br>
  name, file content, subdirectories name), replaces the string (old1) with new string (new1), and so on old2 with new2 ....oldn with newn. </p>
  
  <pre><code>#!/bin/bash
  FILES_PATH="/home/pons/test"
  FILES=$(find $FILES_PATH -type f -name "*")
  for FILE in $FILES; do
      sed -i 's/old1/new1/ ; .... ; s/oldn/newn/' $FILE
  done
  </code></pre>
  
  <p>e.g. replace fadi to server in all</p>
  
  <pre><code>[pons@server1 ~]$ pwd 
  /home/pons 
  [pons@server1 ~]$ cd test
  [pons@server1 test]$ ls -al
  total 12
  
  drwxrwxr-x   3 pons pons 4096 Sep 29 09:50 .
  drwx------. 26 pons pons 4096 Sep 29 10:21 ..
  drwxrwxr-x   2 pons pons 4096 Sep 29 09:47 fadi
  [pons@server1 test]$ cd fadi/ 
  [pons@server1 fadi]$ pwd 
  /home/pons/test/fadi
  [pons@server1 fadi]$ ls -al
  total 12&lt;br/&gt;
  drwxrwxr-x 2 pons pons 4096 Sep 29 09:47 .
  drwxrwxr-x 3 pons pons 4096 Sep 29 09:50 ..
  -rw-rw-r-- 1 pons pons   27 Sep 29 09:47 xxxfadixx.txt
  [pons@server1 fadi]$ cat xxxfadixx.txt 
  xxxxxxxxxxxxfadixxxxxxxxxx
  [pons@server1 fadi]$ 
  </code></pre>
  
  <p>Can I add multiple string in one file and do the replace</p>
  
  <p>e.g. create a file that specify filtering routines: 
      filter.txt <br/>
      s/old1/new1/<br/>
      s/old2/new2/<br/>
      s/old3/new3/<br/>
      ......
      s/oldn/newn/<br/></p>
  
  <p>and then read that file in the script </p>
  
  <pre><code>#!/bin/bash
  
  ROOT_DIR="$HOME/root"  # your target dir
  P_FROM="1.2.3.4"
  P_TO="5.6.7.8"
  
  # for each directory, starting from deepest first
  while IFS= read -r -d $'\0' DIR_NAME; do
  cd "$DIR_NAME"           # go to target dir
  rename $P_FROM $P_TO *   # rename files
  find . -type f -maxdepth 1 -exec sed -i "s/$P_FROM/$P_TO/g" {} \;  
  cd - &gt; /dev/null         # back to original dir. Suppress stdout
  done &lt; &lt;(find $ROOT_DIR -type d -depth -print0) # get only dirs
  </code></pre>
  
  <p>This above script from Shawn Chin worked perfectly replacing/renaming strings, how can I modify it if I have multiple string to be modified and these strings allocated in a file<br>
   filter.txt <br/>
      s/old1/new1/ <br/>
      s/old2/new2/ <br/>
      s/old3/new3/<br/> 
      ......
      s/oldn/newn/ <br/></p>
  
  <pre><code>#!/bin/bash
  ROOT_DIR="$HOME/test"  # your target dir
  FILTER_FILE="$HOME/filter.sed"  # the sed script for renaming
  
  # custom rename function that uses $FILTER_FILE (via sed)
  function rename_using_filter {
  CURRENT_NAME="$1"
  NEW_NAME="$(echo $1 | sed -f $FILTER_FILE)"  # derive new name
  if [ "$CURRENT_NAME" != "$NEW_NAME" ]; then  # rename if diff
      mv "$CURRENT_NAME" "$NEW_NAME"
  fi
  }
  
  # for each directory, starting from deepest first
  while IFS= read -r -d $'\0' DIR_NAME; do
  cd "$DIR_NAME"           # go to target dir
  
  # for each file/dir at this level
  while IFS= read -r -d $'\0' FILE_NAME; do
      rename_using_filter "$FILE_NAME"  # rename it
      if [ -f "$FILE_NAME" ]; then                # if it's a file
          sed -i -f "$FILTER_FILE" "$FILE_NAME";  # replace content
      fi
  done &lt; &lt;(find . -maxdepth 1 -print0)
  
  cd - &gt; /dev/null         # back to original dir. Suppress stdout
  done &lt; &lt;(find $ROOT_DIR -depth -type d -print0) # get only dirs
  </code></pre>
  
  <p>I did the  above with filter.sed, it works replacing name files/directories but didnt replace the content of the file... can you check it please.</p>
  
  <pre><code>[pons@server1 test]$ find .
  .
  ./boy_dir
  ./boy_dir/boy.txt
  ./papa
  ./papa/papa_new
  ./papa/papa_new/papa.txt
  ./boy
  [pons@server1 test]$ cat ./papa/papa_new/papa.txt
  xxxxxxxxxxxxxxxxxxxxpapaxxxxxxxxxxxx
  [pons@server1 test]$ cat ./boy_dir/boy.txt
  xxxxxxxxxxxxboyxxxxxxxxx
  [pons@server1 test]$ cd ..
  [pons@server1 ~]$ ./replace.sh 
  [pons@server1 ~]$ cd test
  [pons@server1 test]$ find .
  .
  ./girl_dir
  ./girl_dir/girl.txt
  ./girl
  ./mama
  ./mama/mama_new
  ./mama/mama_new/mama.txt
  [pons@server1 test]$ cat ./mama/mama_new/mama.txt
  xxxxxxxxxxxxxxxxxxxxpapaxxxxxxxxxxxx
  [pons@server1 test]$ cat ./girl_dir/girl.txt
  xxxxxxxxxxxxboyxxxxxxxxx
  [pons@server1 test]$ 
  
  
  I used this filter 
  [pons@server1 ~]$ cat filter.sed 
  s/papa/mama/g;
  s/boy/girl/g;
  s/old3/new3/g;
  s/old3/new4/g;
  s/oldn/newn/g;
  
  
  
  
  "filter.sed" 5L, 95C written                                                                                      
  [pons@server1 ~]$ ./replace.sh 
  [pons@server1 ~]$ cd test
  [pons@server1 test]$ find .
  .
  ./A.B.C.D.E_
  ./a.b.c.d.e
  ./a.b.c.d.e/a.b.c.d.e
  ./a.b.c.d.e_
  ./A.B.C.D.E
  ./A.B.C.D.E/A.B.C.D.E
  [pons@server1 test]$ cat ./A.B.C.D.E/A.B.C.D.E
  1.2.3.4.5
  [pons@server1 test]$ cat ./a.b.c.d.e/a.b.c.d.e
  6.7.8.9.0
  [pons@server1 test]$ cat ./A.B.C.D.E_
  1.2.3.4.5
  [pons@server1 test]$ cat ./a.b.c.d.e_
  6.7.8.9.0
  [pons@server1 test]$ cd ..
  [pons@server1 ~]$ ./replace.sh 
  [pons@server1 ~]$ cd test
  [pons@server1 test]$ find .
  .
  ./A.B.C.D.E_
  ./a.b.c.d.e
  ./a.b.c.d.e/a.b.c.d.e
  ./a.b.c.d.e_
  ./A.B.C.D.E
  ./A.B.C.D.E/A.B.C.D.E
  [pons@server1 test]$ cat ./A.B.C.D.E/A.B.C.D.E
  A.B.C.D.E
  [pons@server1 test]$ cat ./a.b.c.d.e/a.b.c.d.e
  a.b.c.d.e
  [pons@server1 test]$ cat ./A.B.C.D.E_
  A.B.C.D.E
  [pons@server1 test]$ cat ./a.b.c.d.e_
  a.b.c.d.e
  [pons@server1 test]$
  
  
  [pons@server1 ~]$ vi filter.sed 
  
  s/1.2.3.4.5/A.B.C.D.E/g;
  s/6.7.8.9.0/a.b.c.d.e/g;
  s/old3/new3/g;
  s/old3/new4/g;
  s/oldn/newn/g;
  </code></pre>
  
  <p>~</p>