Assigning the result of 'test' to a variable
You need to quote whitespace:
mytest='[ -f $file ]'
if $mytest; then echo yes; fi
However, this is extremely brittle and potentially insecure. See http://mywiki.wooledge.org/BashFAQ/050 for a detailed discussion and some better ways to accomplish something similar.
If you want to encapsulate a complex piece of code, a function is usually the way to go:
mytest () { [ -f "$file" ]; }
if mytest; then echo yes; fi
If you want to run the code once and store its result so you can examine it later, I would rephrase it like this:
if [ -f "$file" ]; then
mytest=true
else
mytest=false
fi
if $mytest; then echo yes; fi
As others have documented here, using the string "true" is a red herring; this is not an appropriate way to store boolean values in shell scripts, as evaluating it means dynamically invoking a command rather than simply inspecting the stored value using shell builtins hardcoded in your script.
Instead, if you really must store an exit status, do so as a numeric value:
[ -f "$file" ] # run the test
result=$? # store the result
if (( result == 0 )); then # 0 is success
echo "success"
else # nonzero is failure
echo "failure"
fi
If compatibility with set -e
is desired, replace the first two lines of the above with:
result=0
[ -f "$file" ] || result=$?
...as putting the test on the left-hand side of ||
marks it as "checked", suppressing errexit
behavior. (That said, see BashFAQ #105 describing the extent to which set -e
harms predictable, portable behavior; I strongly advise against its use).
mytest=/bin/true
is storing the string /bin/true
in the $mytest
variable.
mytest=[ -f $file ]
is setting the $mytest
variable to the value [
for the duration of the command -f $file ]
(which as your output indicates fails as there is no -f
command available).
mytest= [ -f $file ]
(like the above) sets the value of the $mytest
variable to blank for the duration of the [ -f $file ]
command (and returns whatever [
returns).
mytest= /bin/false
this is the same as the above case only the command being run is /bin/false
.
If you want to store the return code from a command in a variable you can do
/bin/true
ret=$?
if you want to store the output from a command in a variable you can do
out=$(/bin/true)
(though with /bin/true
that variable will be empty as it outputs no text.
For your case you want the former $?
model.
Also, using set -x
(and/or set -v
) in your scripts might have helped you diagnose this.
A old one but left this here for reference for people that might need it. Not the most beautiful solution but it works in bash:
mytest=$( [ -f $file ] ; echo $? )
More portable, using the test command, and the backticks:
set mytest=`test -f $file ; echo $?`
In a subprocess (<!> system load), the condition is evaluated, and then the result echoed to the output that is captured by the variable $mytest.