Unix shell bash script unable to put an echo debug statement - shell

I have the following make file, which i think is a shell script.
I am trying to loop through FILE_DIR to perform some operations. However, i feel that the implementation isn't working as expected. So i am trying to insert some echo breakpoints.
Source:
# Target to recurse through the DIR_LIST and make each makefile found in that DIRS
ALLDIRS:
for se in $(FILE_DIR); do \
if [ -d $se ]; then \
cd $se; \
$(MAKE) -f Makefile.mk all; \
cd ..; \
fi \
done
Running:
$ make -f Makefile.batch
h: syntax error at line 3: `then' unexpected
*** Error code 2
The following command caused the error:
for se in `ls -p /app/internal|grep "/"`; do \
echo "Test" \
if [ -d e ]; then \
cd e; \
/usr/ccs/bin/make -f Makefile.mk all; \
cd ..; \
fi \
done
make: Fatal error: Command failed for target `ALLDIRS'
Can i please get help on this. Would like to insert an echo breakpoint.

One common error in Makefiles is using spaces instead of tabs in a command line. Check the whole for loop and make sure there are only tabs at the beginning of each line
ALLDIRS:
<tab>for se in $(FILE_DIR); do \
<tab><tab>if [ -d $se ]; then \
<tab><tab>cd $se; \
<tab><tab>$(MAKE) -f Makefile.mk all; \
<tab><tab>cd ..; \
<tab><tab>fi \
<tab>done
Another error is the dollar sign $. If you want a dollar sign in the shell command, you must double it in your commands, because otherwise dollar introduces a make variable and will be expanded before the shell sees it.
for se in $(FILE_DIR); do \
if [ -d $$se ]; then \
cd $$se; \
$(MAKE) -f Makefile.mk all; \
cd ..; \
fi \
done
And the final one, echo Test needs a semicolon as well
for se in $(FILE_DIR); do \
if [ -d $$se ]; then \
echo "Test"; \
cd $$se; \
...

Related

Add a conditional SORT variable to mongoexport

I'm trying to set up a conditional --sort option in mongoexport but I'm having trouble with the string interpretation of my variable.
Here is the code I'm trying to run :
#!/bin/bash
if [[ $IS_PROD == "true" ]]
then
SORT='--sort "{_id : -1}"'
else
SORT=""
fi
$MONGODB_HOME/bin/mongoexport \
--host=$HOST \
--port=$PORT \
--username=$USER \
--password=$PWD \
--db=$DB \
--limit=$LIMIT \
$SORT \
--collection=my_collection | \
sed 's,\\,\\\\,g' \
> $TMP_FILE
While running this I get the following error error parsing command line options: invalid argument for flag '--sort' (expected string): invalid syntax
I've tried several quotes configuration and still couldn't make it work. Could someone please help me on this one?
Thanks
using bash array
#!/bin/bash
if [[ $IS_PROD == "true" ]]
then
SORT=(--sort "{_id : -1}")
else
SORT=()
fi
$MONGODB_HOME/bin/mongoexport \
--host=$HOST \
--port=$PORT \
--username=$USER \
--password=$PWD \
--db=$DB \
--limit=$LIMIT \
"${SORT[#]}" \
--collection=my_collection | \
sed 's,\\,\\\\,g' \
> $TMP_FILE
Explanation: using single quotes prevent shell expansions and double quotes are literal, but after variable expansion the double quotes are still litteral and expanded string is split by spaces.
Otherwise to work around unbound variable bug
#!/bin/bash
options=(--host=$HOST \
--port=$PORT \
--username=$USER \
--password=$PWD \
--db=$DB \
--limit=$LIMIT)
if [[ $IS_PROD == "true" ]]
then
options+=(--sort "{_id : -1}")
fi
$MONGODB_HOME/bin/mongoexport \
"${options[#]}" \
--collection=my_collection | \
sed 's,\\,\\\\,g' \
> $TMP_FILE

Makefile does not work, #if, #else, #then not found

This is the section of my Makefile which fails
b2dsetup:
#$(ECHO) "Goes in b2dsetup"; \
#if [-d "/external/src/Box2D"]; \
#then $(PRINTF) "Option1"; \
#else; \
#$(ECHO) "Option2"; \
#cd /external/src/; \
#tar cfv Box2D.tgz Box2D; \
#fi;
and gives the following error:
Goes in b2dsetup
bash: line 1: #if: command not found
bash: line 2: #then: command not found
bash: line 3: #else: command not found
bash: line 4: #/bin/echo: No such file or directory
bash: line 5: #cd: command not found
bash: line 6: #tar: command not found
bash: line 7: #fi: command not found
Makefile_g30:71: recipe for target 'b2dsetup' failed
make: *** [b2dsetup] Error 127
shell returned 2
I tried lots of syntactical changes and googling but nothing helps.
Only put the # on the first line of a multiline script.
b2dsetup:
#$(ECHO) "Goes in b2dsetup"; \
if [-d "/external/src/Box2D"]; \
then $(PRINTF) "Option1"; \
else \
$(ECHO) "Option2"; \
cd /external/src/; \
tar cfv Box2D.tgz Box2D; \
fi
Or:
b2dsetup:
#$(ECHO) "Goes in b2dsetup"
#if [-d "/external/src/Box2D"]; \
then $(PRINTF) "Option1"; \
else \
$(ECHO) "Option2"; \
cd /external/src/; \
tar cfv Box2D.tgz Box2D; \
fi

Nested For loop in makefile

I am trying to loop through the .c files in a specific directory through the makefile.
i used the following code, but it seems not working:
DIR= Sources \
Sources_2
#for entry in ${DIR} ; \
do \
#for i in $${entry}/*.c ; \
do \
echo "Processing $${i}"; \
#Building Commands go here
done \
done
I get error: "/bin/sh: -c: line 3: syntax error near unexpected token `do'"
You shouldn't use at sign # near the second for loop. # should be used at the beginning of the whole shell command. The following worked for me:
DIR= Sources \
Sources_2
all:
#for entry in ${DIR}; \
do \
for i in $${entry}/*.c; \
do \
echo "Processing $${i}"; \
done \
done
Change the Makefile as below
#for entry in ${DIR} ; do \
for i in $$entry/*.c ; do \
echo "Processing $$i"; \
#Building Commands go here
done \
done
The reason being wrong syntax usage of for loop.

Makefile (running outside scripts that have makefile macros)

I have some .PHONY targets such as 'clean', 'backup', and 'help'
the rule for some of these targets is very large.
For example:
.PHONY: backup
backup:
#$(GREEN)
#mkdir -p backup/include #make an backup include folder if it doesn't already exist
#mkdir -p backup/src #make a backup src folder if it doesn't already exist
#mkdir -p backup/docs #make a backup docs folder if it doesn't already exist
#total=0; headerCount=0; sourceCount=0; documentCount=0; \
for file in $(HEADER_PATH)*; do \
if ls $$file[~] >/dev/null 2>&1; then \
mv -fu $$file[~] backup/$$file; \
let "headerCount+=1"; \
echo $(DATE)[Backed Up] $$file~ >> $(LOG); \
fi; \
done; \
for file in $(SOURCE_PATH)*; do \
if ls $$file[~] >/dev/null 2>&1; then \
mv -fu $$file[~] backup/$$file; \
let "sourceCount+=1"; \
echo $(DATE)[Backed Up] $$file~ >> $(LOG); \
fi; \
done; \
for file in $(DOC_PATH)*; do \
if ls $$file[~] >/dev/null 2>&1; then \
mv -fu $$file[~] backup/$$file; \
let "documentCount+=1"; \
echo $(DATE)[Backed Up] $$file~ >> $(LOG); \
fi; \
done; \
let "total= headerCount + sourceCount + documentCount"; \
echo -n $(OUTPUT_PROMPT)" "; \
if test $$total -eq 0; then \
echo Nothing To Back up; \
else \
if test $$headerCount -eq $$total; then \
echo -n $$total" "; \
echo -n "Header"; \
if test $$total -ge 2; then \
echo -n "s"; \
fi; \
echo " Backed Up"; \
elif test $$sourceCount -eq $$total; then \
echo -n $$total" "; \
echo -n "Source"; \
if test $$total -ge 2; then \
echo -n "s"; \
fi; \
echo " Backed Up"; \
elif test $$documentCount -eq $$total; then \
echo -n $$total" "; \
echo -n "Document"; \
if test $$total -ge 2; then \
echo -n "s"; \
fi; \
echo " Backed Up"; \
else \
$(UNDERLINE); echo $$total " Files Backed Up"; $(UNUNDERLINE); \
if test $$headerCount -eq 1; then \
echo $(OUTPUT_PROMPT)" "$$headerCount header; \
elif test $$headerCount -ge 2; then \
echo $(OUTPUT_PROMPT)" "$$headerCount headers; \
fi; \
if test $$sourceCount -eq 1; then \
echo $(OUTPUT_PROMPT)" "$$sourceCount source; \
elif test $$sourceCount -ge 2; then \
echo $(OUTPUT_PROMPT)" "$$sourceCount sources; \
fi; \
if test $$documentCount -eq 1; then \
echo $(OUTPUT_PROMPT)" "$$documentCount document; \
elif test $$documentCount -ge 2; then \
echo $(OUTPUT_PROMPT)" "$$documentCount documents; \
fi; \
fi; \
fi;
#$(DEFAULT_TEXT)
what the code does is not important, but I wanted to illustrate that it has macros in which 'make' must expand, and that it also performs shell code (bash), and that some indication on what the script did, is displayed in the terminal.
I want to put this script outside of 'make' in another directory, and turn that code into something like this:
.PHONY: backup
backup:
#run scripts/backup.scr
#or something similar to that
How can I put the rule of my target (which is makefile/bash code) into a separate file, and have make practically paste it in so that it runs how I had it originally?
I thought I might be able to use the "include" command inside 'make'.
It looks like it is used to include other makefiles though..
maybe I should just paste the entire target/rule into another makefile, and then include that makefile into my main one?
Would that be the best way?
In your case, you have quite few output variables. It might be worth the hassle to separate the generation and execution, like:
clean : clean-script
sh clean-script
rm -f clean-script
clean-script : clean-script.in
sed -e 's:[#]HEADER_PATH[#]:$(HEADER_PATH):g' $<.in > $#
And write clean-script.in as a clean sh script with a few substitutions.
If you use GNU make, you can of course build a list of output varables like:
clean-script : clean-script.in
sed $(foreach var,$(SUBSTVARS),-e 's:[#]$(var)[#]:$($(var)):g') $<.in > $#
I don't know if it can help you, but you can run make inside some Makefile usually with a command (inside a rule) e.g.
$(MAKE) subtarget
See the section Recursive use of Make in the GNU make documentation.
I tend to dislike using make for complex projects (but unfortunately, I have to). If you are free to chose some other tool, you might consider omake and many others (cmake, scons, bake, ...)

Problem in Makefile

I am executing the following command in Makefile:-
#ls export_mojave/marker_*.tcl > export_mojave.list
#for file in `cat export_mojave_tcl_files.list`; do \
diff $$file bk_marker > $$file.diff ; \
if ! [ -s $$file.diff ]; then\
rm -f $$file.diff ; \
else \
echo $$file >> marker.fill.tcl.diff; \
fi \
done ;
If there exists some file related to the above expression in the mentioned directory,
it will run fine but if there does not exits any files matching to above expression, It is marking an error. Is there anything exists like "catch" in Makefile?
If you need to skip error in makefiles' rule, then prefix command with '-' sign:
-#ls .... > some_file || echo Error: no file;
if [ -e some_file ] ....
Or modify to be more in make-style:
FILES := $(shell ls ...)
ifeq ($(FILES),)
$(error no files)
endif
....
target:
$(foreach file,$(FILES), ...)

Resources