0

I am trying to write a Bash script that will process all files in a folder structure that match a pattern (e.g. *.properties or *.conf). My use case is replacing a server name (server-xx) with another server name (server-yy) in a myriad of application configuration files.

Basically, it's all about finding all files in the folder structure starting from a root, and applying the same processing to all files.

I'm slowly building the script and it's getting much more difficult than my initial intention hinted to. It has four parameters:

  • root path
  • file pattern
  • string to replace
  • replacement string

Here it is in its current state:

# The echoing of usage notes is omitted here.
nbArgs=$#

if [[ $nbArgs -ne 4 ]]
then
    echo "Four parameters are required."
else
    echo "Running..."

    filelist=`find $1 -name "$2" 2> /dev/null`
    printf "Files: $filelist"
    echo

    while read filename ; do
    if [[ -e $filename ]]; then
        line="sed -i 's/$3/$4/g' $filename"
        echo "Executing $line"
    fi
    done <<< "$filelist"

    echo "Done. Exiting."
fi

Example run: ./adapt-properties-files.sh /mnt/c/Users/avoglozin/Apps/test-adapt/ "*.properties" server-xx.domain.com server-yy.domain.com

The target "production" environment for this script is an Ubuntu proper machine, but I'm using the Ubuntu Bash under Windows 10 for development.

The problem is that when I run the find command, e.g. find ./test-adapt/ -name "*.properties" 2> /dev/null in the shell, I get the correct list of files shown in the terminal. However, when I run the script, the filelist variable shows only one file. Some possibly obvious piece of knowledge is evading me.

Biffen
  • 6,249
  • 6
  • 28
  • 36
AbVog
  • 1,435
  • 22
  • 35
  • Does the file have a hashbang-line like so: `#! /bin/sh` or `#! /bin/bash` ? If former, try the latter. – Olli K Sep 14 '18 at 10:07
  • Your script contains a large number of common errors. I tried to add duplicates for the most important ones but in short, you want something like `find "$1" -name "$2" -exec sed -i "s/$3/$4/" {} +` where you should pay attention to the quoting and possibly add some frills to cope with regex escaping etc. Trying to do things piecemeal while storing intermediate results in simple scalar variables is creating a large number of complications; see also https://mywiki.wooledge.org/BashFAQ/050. Finally, please check out http://shellcheck.net/ for automated diagnostics for many of these errors. – tripleee Sep 14 '18 at 11:04
  • https://mywiki.wooledge.org/UsingFind is also a good resource which points out many of the tricky corner cases. – tripleee Sep 14 '18 at 11:06
  • @OlliK yes, the file contains a bash hashbang. – AbVog Sep 14 '18 at 11:13
  • @tripleee Indeed, a large number of complications, but some intermediates variables were added while trying to debug the problem. Thx. – AbVog Sep 14 '18 at 11:15

1 Answers1

0

In my opinion this could be shortened to

find "$1" -name "$2" -type f -exec sed -i -e "s/$3/$4/g" {} +
JGK
  • 3,710
  • 1
  • 21
  • 26
  • This will fail if `find` returns a file name which contains whitespace or a literal shell metacharacter. This is a common FAQ. – tripleee Sep 14 '18 at 10:59
  • Check this https://mywiki.wooledge.org/BashFAQ/001. Your solution works in the majority of cases, but on SO it is better to answer with the solution that will always work (disclosure, I learned that exact same thing a couple months ago :-) – Nic3500 Sep 14 '18 at 13:37