Reputation: 2234
I am creating a function (below) with which you can provide an argument, a directory. I test if the $argv
is a directory with -d
option, but that doesn’t seem to work, it always return true even if no arguments are supplied. I also tried test -n $argv -a -d $argv
to test is $argv
is empty sting, but that returns test: Missing argument at index 1
error. How should I test if any argument is provided with the function or not? Why is test -d $argv
not working, from my understanding it should be false when no argument is provided, because empty string is not a directory.
function fcd
if test -d $argv
open $argv
else
open $PWD
end
end
Thanks for the help.
Upvotes: 37
Views: 21463
Reputation: 7444
if not set -q argv[1]
echo 'none'
else
echo 'yes'
end
From the man set
page:
set ( -q | --query ) [SCOPE_OPTIONS] VARIABLE_NAMES...
-q
or --query
test if the specified variable names are defined. Does not output anything, but the builtins exit status is the number of variables specified
that were not defined.
Upvotes: 15
Reputation: 9323
Maybe is non related, but i would like to add another perspective for the question.
I want to broaden the insight to a wider scope the scope of testing the shell code with the libraries developed in the fisherman group.
With mock you can check if the open command is called safely without side effects.
Example.:
function fcd
if count $argv > /dev/null
open $argv
else
open $PWD
end
end
mock open 0 "echo \$args"
fcd "cool" # echoes cool
mock open 0 "echo \$args"
fcd # echoes $PWD
Is a recent library, but it could help to test things that might be dangerous, like for example rm
mock rm 0 "echo nothing would happen on \$args"
rm "some file" # simply echoes the message with a list of the files that would been affected
I hope that it gives a more out of the box point of view
P.S.: Sorry for the blatant publicity, but i think that is a cool idea that would be nice to be adopted by shell scripters, to test and add sustainability to shell scripts is nuts. :P
EDIT: i recently noticed a bug about the sample i posted. Please do not use rm *, because the asterisk is not treated as a param, instead fish shell expands asterisk to the list of files found and the command only mocks the first call, this means that the first file would be ignored by the mock, but all the subsequent files will get erased so please be careful if trying the sample and use a single file for the example not the wildcard.
Upvotes: 4
Reputation: 2558
In fish 2.1+ at least, you can name your arguments, which then allows for arguably more semantic code:
function fcd --argument-names 'filename'
if test -n "$filename"
open $filename
else
open $PWD
end
end
Upvotes: 34
Reputation: 18551
count
is the right way to do this. For the common case of checking whether there are any arguments, you can use its exit status:
function fcd
if count $argv > /dev/null
open $argv
else
open $PWD
end
end
To answer your second question, test -d $argv
returns true if $argv
is empty, because POSIX requires that when test
is passed one argument, it must "Exit true (0) if $1 is not null; otherwise, exit false". So when $argv is empty, test -d $argv
means test -d
which must exit true because -d
is not empty! Argh!
edit Added a missing end
, thanks to Ismail for noticing
Upvotes: 49
Reputation: 246774
$argv
is a list, so you want to look at the first element, if there are elements in that list:
if begin; test (count $argv) -gt 0; and test -d $argv[1]; end
open $argv[1]
else
open $PWD
end
Upvotes: 6