M BUZZ CRAZE NEWS
// general

bash shell script, searching for complex line in makefile (shell parameter expansion issue)

By David Jones

I have an annoying problem, I want a script to search through a makefile (using grep) for a particular annoying line. The problem is best illustrated concretely:

someMakefile (minimal Makefile):

#!/usr/bin/env bash
echo bla bla
OBJ_DIR='something'
EXE_FILE='my_exe'
cp $(OBJ_DIR)/$(EXE_FILE) ../bin/.
echo 'doing something else now'

testScript.sh (test for the existence of the difficult line):

cat testScript.sh

#!/usr/bin/env bash
set -x
foundNumLines = $(grep -in 'cp $(OBJ_DIR)/$(EXE_FILE) ../bin/.' someMakefile)
echo "foundNumLines = $foundNumLines"
set +x

From the commandline (this DOES work):

$ grep -in 'cp $(OBJ_DIR)/$(EXE_FILE) ../bin/.' someMakefile
5:cp $(OBJ_DIR)/$(EXE_FILE) ../bin/.

From the script (this does NOT work and I cannot figure out how to make it work):

$ ./testScript.sh
++ grep -in 'cp $(OBJ_DIR)/$(EXE_FILE) ../bin/.' someMakefile
+ foundNumLines = 5:cp '$(OBJ_DIR)/$(EXE_FILE)' ../bin/.
./testScript.sh: line 4: foundNumLines: command not found
+ echo 'foundNumLines = '
foundNumLines =
+ set +x

When "grep" works from the script, I wanted to use maybe "wc" or similar, to detect the presence of the line and then do something, based on this...

I just cannot make it work, tried many combinations of "'" \' etc - I hope you understand, what I'm trying to achieve, please help with ideas/suggestions, thanks!

0

1 Answer

To assign values to variables, you need var=value and not var = value. Spaces are significant in this context and that's why you get the command not found error from this line:

foundNumLines = $(grep -in 'cp $(OBJ_DIR)/$(EXE_FILE) ../bin/.' someMakefile)

That isn't a variable assignment, it is three commands: foundNumLines, =, and $(grep ... ). What you need is:

foundNumLines=$(grep -in 'cp $(OBJ_DIR)/$(EXE_FILE) ../bin/.' someMakefile)

I know you said it was a makefile, but I should point out that the $() construct has meaning in the shell as well. $(foo) will run the command foo and return its output. Therefore, this line:

cp $(OBJ_DIR)/$(EXE_FILE) ../bin/.

Will first try to execute $OBJ_DIR and $EXE_FILE as commands and insert their output in the place of the variables. Since OBJ_DIR will presumably not be a command, this means that you will be executing

cp / ../bin/.

Or, if EXE_FILE is in your path and executable:

cp /$outputOfExec_File ../bin/.

(by the way, there's no need for . there, ../bin/ is the same as ../bin/.).

I thought I'd mention this since you have a bash shebang at the top of your makefile example, so I am assuming you are executing it as a shell script.

2

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy