Why doesn't the conditional work when I use it directly without a variable?
Couple of issues:
]
indicates the end of arguments for[
(test
), and it must be the last argument; you have couple of]
s, which is wrong; presumably you meant to use:if [ $( file -b $i ) == "directory" ]
If you had used the above, you would get
bash: [: too many arguments
, because word splitting would be done upon on the output of the variable expansion ($i
), and then command substitution,$()
(file
command) and[
will see multiple words before=
, leading to the error message. You need to quote the variable expansion, and command substitution:[ "$(file -b "$1")" == "directory" ]
As a side note, you should use the bash
keyword [[
, instead of [
as the former will handle word splitting (and pathname expansion) for you.
if [ $( file -b $i ) == "directory" ]
Two issues here:
Use single
=
for string comparison. Seeman test
for proper syntax( note, that[
in many cases has shell-specific implementation, so see your shell'sman page
if you don't have documentation fortest
). If you absolutely need==
, use[[
instead, which is feature of many bourne-like shells, including bash,ksh,zsh. NOTE: while==
exists in bash since version 2.0, " = should be used with the test command for POSIX conformance." ( bash man page).Quote all your variables as
"$()"
. Specifically of interest is$i
. Filenames with space will break$i
into multiple words due to shell's word expansion.
Example:
bash-4.3$ mkdir with\ space
bash-4.3$ i="./with space"
bash-4.3$ set -x
bash-4.3$ [ $( file -b $i ) == "directory" ] && echo "YES"
++ file -b ./with space
+ '[' cannot open '`./with'\''' '(No' such file or 'directory)' cannot open '`space'\''' '(No' such file or 'directory)' == directory ']'
bash: [: too many arguments
name=$( file -b $i )
if [ name == "directory" ]
Issues here:
name
is not expanded to variable, it's just a string "name" here. You need"$name"
and again, single=
Also, it cannot have possibly have worked , since exit status of test
is returned as false ( exit status 1)
$ name=$(file -b /etc)
$ set -x
$ [ name == "directory" ]
+ '[' name '==' directory ']'
$ echo $?
+ echo 1
1
The above tested on bash
and mksh
shells.
There are lots of issues! Let’s take this part which is "working":
name=$( file -b $i )
if [ name == "directory" ]
This assigns the output of the file command to the variable called name
, but doesn't use it; instead, it runs the [
command with 3 parameters: name
, ==
, and directory
. Accepting ==
is a bash extension.
If this was corrected to use $name
rather than name
you would again get a too many arguments
problem for many cases. This is because file
returns multiple word results like ASCII text
. So after the command has run you get
if [ ASCII text == directory ]
and now it is obvious that the command is missing some grouping.
if [ "$(file -b -- "$i")" = "directory" ]
is probably what you want: =
rather than ==
for portability, and quoting the result of command substitution which you almost always want to do.