I am trying to implement a simple string comparison to get the type of a file (using its extension) like this:
extract_pkg: $(PKG)
$(eval EXT := $(suffix $(PKG)))
#echo $(EXT)
ifeq ($(EXT), .zip)
#echo "is zip file"
else
#echo "is not a zip file"
endif
extract_pkg : PKG = mypkg.zip
However, when I run it it goes into the else branch. My guess is, it has to do with the dot, but I dont find a solution. Thanks for your help !
Edit 1: the essential code would be actually somewhat like the following, and it works as expected:
test_cmp:
ifeq (.zip,.zip)
#echo ".zip==.zip"
endif
ifeq (zip,zip)
#echo "zip==zip"
endif
thus the problem is somewhere else !
One thing to be careful about -- spaces in if constructs are significant. So if you have something like:
ifeq ($(EXT), .zip)
it will only match if $(EXT) expands to exactly ".zip" -- including the space before the period. So your first example will always print is not a zip file, since $(EXT) will never contain the space.
You cannot use ifeq() etc. inside recipes. ifeq() are preprocessor statements: they are interpreted immediately as the makefile is read in. Recipes are not run until much later, after all makefiles are parsed and make decides that this target needs to be updated. So trying to set a variable in a recipe using eval, etc. then test that variable using ifeq() cannot work.
You have to use shell constructs for this; something like:
extract_pkg: $(PKG)
#EXT=$(suffix $<); \
echo $$EXT; \
if [ $$EXT = .zip ]; then \
echo "is zip file"; \
else \
echo "is not a zip file"; \
fi
Related
I noticed that tab completion for the source command in Zsh tries to complete a LOT of files. Maybe everything in $PATH? I tried using a blank .zshrc file to make sure it wasn't anything in there.
ubuntu% source d
zsh: do you wish to see all 109 possibilities (16 lines)?
I did find this file that seems to control that: /usr/share/zsh/functions/Completion/Zsh/_source
#compdef source .
if [[ CURRENT -ge 3 ]]; then
compset -n 2
_normal
else
if [[ -prefix */ && ! -o pathdirs ]]; then
_files
elif [[ $service = . ]]; then
_files -W path
else
_files -W "(. $path)"
fi
fi
If I change the line in that last "else" statement from _files -W "(. $path)" to _files, it works the way I want it to. The tab completion only looks at files & directories in the current dir.
It doesn't seem like altering this file is the best way to go. I'd rather change something in my .zshrc file. But my knowledge of Zsh completions is a bit lacking and the searching I've done thus far hasn't led me to an answer for this.
Maybe everything in $PATH?
Yes, that is correct. It offers those, because source will search your the current dir and your $PATH for any file name you pass it.
To apply your change without modifying the original file, add this to your .zshrc file after calling compinit:
compdef '
if [[ CURRENT -ge 3 ]]; then
compset -n 2
_normal
else
_files
fi
' source
This tells the completion system to use the inline function you specified for the command source (instead of the default function).
Alternatively, to see file completions for the current dir only, you can type
$ source ./<TAB>
This is my make recipe, I'm passing nonle value *, although bamboo_nonle_password variable is having password, still function is failing
validatevar.%: $(if $(IS_BAMBOO),)
#echo "\n################################################################################"
#echo ">>> validatevar"
#echo ">>> Start: Validate bamboo variables "
ifndef bamboo_$*_password
#echo "Bamboo variable bamboo_$*_password is empty"
exit 1
endif
ifndef bamboo_$*_server
#echo "Bamboo variable bamboo_$*_server is empty"
exit 1
endif
#echo "<<< Done: validatevar"
#echo "################################################################################\n\n"
You crazy person :)
Make will expand the recipe just before it wants to execute it.
At this point make knows what the % corresponds to,
and so can ensure $* is set appropriately.
Unfortunately, the ifndef…endif pair is evaluated as the makefile is read,
not as the recipe is expanded.
This suggests the answer:
use macros.
Maybe $(origin …) or $(flavor …) in something like
validatevar.%:
#echo
$(if $(filter undefined,$(origin bamboo_$*_password)),#echo "Bamboo variable bamboo_$*_password is undefined")
$(if $(filter undefined,$(origin bamboo_$*_password)),exit 1)
Naturally you can tidy this up a bit.
Maybe:
die-if-undefined = $(if $(filter undefined,$(origin $1)),$(error "$1" is undefined))
validatevar.%:
$(call die-if-undefined,bamboo_$*_password)
$(call die-if-undefined,bamboo_$*_server)
#echo
#echo
Two things to note:
The whole of the recipe is expanded in one go, before any of the lines are executed.
The upshot of this is that it doesn't matter where you expand the $(error) assertions.
I have put them at the top.
ifndef also detects empty variables, as well as undefined ones. You may wish to adjust die-if-undefined to take account of this (and rename it to die-if-empty).
(This would all be a lot easier if make would only take a --error-undefined-variables parameter,
just to match the existing --warn-undefined-variables parameter.)
Problem is, furl doesn't get assigned value from file variable. If I use any plain text instead of $$file, it works. I have no idea why this doesn`t work.
Makefile:
test:
#for file in $(shell pwd)/demo/*; do \
$(eval furl := $(shell echo $$file)) \
echo $(furl); \
done
Im pretty sure this should be easy to fix, however I could not find a solution. Any ideas?
Im using the latest lubuntu OS.
You have messed shell and Make variables in the recipe. I think furl should be shell variable. Something like this:
test:; #for file in demo/*; do \
furl="`echo $$file`"; \
echo "$$furl"; \
done
In general you shouldn't assign Make variables in recipes. Obvious exception is $(foreach).
I have two directories, I would like to do something based on the results of a comparison.
Below is my script
#!/bin/sh
# the script doesn't work below if a the above line says bash
for i in $(\ls -d /data_vis/upload/);
do
diff ${i} /data_vis/upload1/;
done
The output from the above script is
Common subdirectories: /data_vis/upload/2012_06 and /data_vis/upload1/2012_06
Common subdirectories: /data_vis/upload/2012_07 and /data_vis/upload1/2012_07
Only in data_vis/upload/: 2012_08
Only in /data_vis/upload/: 2012_09
Only in /data_vis/upload/: index.php
Only in /data_vis/upload/: index.php~
Question ?
How can I use this this output to do something e.g. see below
Pseudocode
if Only in data_vis/upload/: 2012_08 # e.g if directory only exists in upload directory
then do something
else
do something else
Finish
Any comments or better solutions/commands welcome!
I understood that You want to parse the output of the diff.
First, Your outermost for-loop is not necessary, since the "ls"-operation returns only one item. The task could be done as follows:
#!/bin/sh
diff data_vis/upload/ data_vis/upload1/ | while read line
do
if echo $line | grep "Only in">/dev/null;then
# parse the name of the directory where the not matched dir is located
dironlyin=$(echo $line|awk -F ":" '{split($1,f," ");print f[3];}');
# parse the name of the not matched dir
fileonlyin=$(echo $line|awk -F ":" '{l=length($2);print substr($2,2,l-2);}');
# prove that the parsing worked correctly
echo "do something with file \""$fileonlyin"\" in dir \""$dironlyin"\""
else
# do your own parsing here if needed
echo "do something else with "\"$line\"
fi
done
You need to do the parsing of the lines starting with "Common subdirectories" by yourself. I hope the awk mini-scripts can help You doing it!
Cheers
Jörg
I am creating a KSH interface script that will call other scripts based on the users input. The other scripts are Encrypt and Decrypt. Each one of these scripts receive parameters. I have seen someone execute a script before using "-" + first letter of a script name before. How do I do this for my script? So for example if my script is called menu and the user typed in : menu -e *UserID Filename.txt* the script would run and the encrypt script would be executed along with the associated parameters. So far my script takes in the encrypt/decrypt script option as a parameter. Here is my script:
#!/bin/ksh
#I want this parameter to become an
action=$1
if [ $1 = "" ]
then
print_message "Parameters not satisfied"
exit 1
fi
#check for action commands
if [ $1 = "encrypt" ]
then
dest=$2
fileName=$3
./Escript $dest $fileName
elif [ $1 = "decrypt" ]
then
outputF=$2
encryptedF=$3
./Dscript $outputF $encryptedF
else
print "Parameters not satisfied. Please enter encrypt or decrypt plus-n arguments"
fi
Thanks for the help!
There isn't any kind of automatic way to turn a parameter into another script to run; what you're doing is pretty much how you would do it. Check the parameter, and based on the contents, run the two different scripts.
You can structure it somewhat more nicely using case, and you can pass the later parameters directly through to the other script using "$#", with a shift to strip off the first parameter. Something like:
[ $# -ge 1 ] || (echo "Not enough parameters"; exit 1)
command=$1
shift
case $command in
-e|--encrypt) ./escript "$#" ;;
-d|--decrypt) ./dscript "$#" ;;
*) echo "Unknown option $command"; exit 1 ;;
esac
This also demonstrates how you can implement both short and long options, by providing two different strings to match against in a single case statement (-e and --encrypt), in case that's what you were asking about. You can also use globs, like -e*) to allow any option starting with -e such as -e, -encrypt, -elephant, though this may not be what you're looking for.