0

How can I delete a particular if statement in shell script file (say file.sh) and do the same for all files (file.sh) of all folders inside a single folder using for loop to find the file?

Detailed explanation:

I have a folder A. It has various folders inside it, suppose B, C, D, E... etc. All/some folders of B, C, D, E...etc have two files, file1.sh and file2.sh. These two files, file1.sh and file2.sh have one if statement.

if [ $usertype != "adm" ]
then
    echo "deploy can only be run with dtp?adm account."
    exit 1
fi

I want to write a script which will take folder A as argument, check for files, file1.sh and file2.sh inside each of its subfolders B, C, D, E... etc. If these files are found, it is going to check for above if statement and if it is present, it should delete this complete if statement from if to fi, save the file and exit.

chepner
  • 497,756
  • 71
  • 530
  • 681
gtaware
  • 103
  • 5
  • Note that `if` statements are not loops. Suppose a folder only has `file1.sh` and not `file2.sh` but it contains the `if` statement; should the file be edited? Suppose a folder has `file3.sh` containing the `if` statement; should the file be edited? I note that the `if` statement has no quotes around the variable where it would be a good idea to have them, and has quotes around the literal where they aren't necessary (but I'd probably put/keep them there for symmetry/clarity). However, since they're going, it isn't a big problem. You'll need to look at `sed`, and check the `-i.bak` option. – Jonathan Leffler Apr 23 '15 at 14:23
  • Jonathan Leffler, Your doubts are --> Suppose a folder only has file1.sh and not file2.sh but it contains the if statement; should the file be edited? Suppose a folder has file3.sh containing the if statement; should the file be edited? **Answer to this question is yes, but if statement should have exactly same condition as above**, I mean condition `$usertype != "adm"` – gtaware Apr 23 '15 at 14:48

3 Answers3

2

Assuming the given folder is the current directory, ., then you might be able to use:

find . -type f -name '*.sh' -exec \
    sed -i.bak '/if [ $usertype != "adm" ]/,/fi/d' {} +

This assumes that the test doesn't appear under any other circumstances, and simply removes the lines between the if and the next fi. The files are backed up just in case something goes wrong. It looks for all .sh files under the given directory. The + at the end works in modern versions of find, actually rather like xargs. There are ways around it if your find does not support +; the simplest is to use \; or ';' in place of the +, but it means sed will be executed once per file instead of once for many files.

If there is more checking needed, so the then, echo and exit need to be matched, then I'd probably switch to Perl and use a 'paragraph' reading mode to read the file in multiline chunks and delete a chunk only if it matches the entire block of text.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0

I mustnot comment so I try it this way: Maybe deleting the if statements is not necessary, use sed/awk to change the if statements to a condition which is always false, for example:

if [ "a" == "b" ] # if [ $usertype != "adm" ]
then
...
fi

Examples of replacing whole lines using sed/awk:

bash: replace an entire line in a text file

change a line with awk

Community
  • 1
  • 1
Thomas
  • 103
  • 1
  • 1
  • 7
-1

I have written a simple shell script by using SED command now. Thanks Thomas for suggestion.

 for file in `find $1 -type f -name "deploy*.sh" -print 2>/dev/null`
do
echo "File checked : $file"
sed 's/\$usertype/adm/g' $file > $file.new
mv $file.new $file
done

And it works for me as expected. Please note, there is only one if condition in every deploy*.sh file which contain $usertype.

So if condition becomes like this after script execution,

if [ adm != "adm" ] 
    then
    ...
fi

because of which control never enters if loop. Thanks everyone for your help

gtaware
  • 103
  • 5
  • Never do this: `for x in $(command)` or `$var`. *for-in* is used for iterating arguments, not (output) strings. Instead, use a glob (eg. `*.txt`), arrays (eg. `"${names[@]}"`) or a while-read loop (eg. `while read -r line`). See [Bash Pitfalls 1](http://mywiki.wooledge.org/BashPitfalls#pf1) and [Don't read lines with for](http://mywiki.wooledge.org/DontReadLinesWithFor). – Rany Albeg Wein May 14 '16 at 18:40
  • "Double quote" every literal that contains spaces/metacharacters and **every** expansion: `"$var"`, `"$(command "$var")"`, `"${array[@]}"`, `"a & b"`. See http://mywiki.wooledge.org/Quotes, http://mywiki.wooledge.org/Arguments and http://wiki.bash-hackers.org/syntax/words . – Rany Albeg Wein May 14 '16 at 18:40