user3016065
user3016065

Reputation: 7

bash passing arguments/parameters?

#!/bin/bash

traverse() {
local x=$1
if [ -d $x ]
then
lst=(`ls $x`)
for((i=${#lst[@]}; --i;)); do
    echo "${lst[i]}"
    done
else echo "not a directory"
fi
}

traverse

I want to pass a parameter such as "/path/to/this/directory/" when executing program but only works if I'm running the program in the same directory as my bash script file and any other parameter I pass is completely ignored.

the script is supposed to take a parameter and check if it's a directory and if it's a directory then list all the files/folders in descending order. If not display error message.

What is wrong with code, thanks!

Upvotes: 0

Views: 103

Answers (3)

glenn jackman
glenn jackman

Reputation: 246807

"That other guy" has the right answer. The reason it always looks at the current directory:

  1. you invoke traverse with no arguments
  2. the $1 in the traverse function is empty, therefore $x is empty
  3. the test is therefore [ -d ], and when [ is given 1 argument, it returns success if the argument is not empty. Your if command always executes the "true" block and ls $x is just ls when x is empty

Use [[ ... ]] with bash: it is smarter about empty arguments. Otherwise, quote your variables:

$ x=; [ -d $x ] && echo always true || echo not a directory
always true
$ x=; [[ -d $x ]] && echo always true || echo not a directory
not a directory
$ x=; [ -d "$x" ] && echo always true || echo not a directory
not a directory

Upvotes: 0

anubhava
anubhava

Reputation: 785128

You don't need to call ls for that. You can use this code:

traverse() {
    local x="$1"
    if [ -d "$x" ]; then
        arr=( "$x/"* )
        for ((i=${#arr[@]}; i>0; i--)); do
           echo "${arr[$i]}"
        done
    else
        echo "not a directory"
    fi
}

Upvotes: 3

that other guy
that other guy

Reputation: 123470

This happens because $1 in the function refers to traverse's parameters, not your script's parameters.

To run your function once with each argument, use

for arg in "$@"   # "$@" is also the default, so you can drop the 'in ..'
do
  traverse "$arg"
done

If you in the future want to pass all the script's parameters to a function, use

myfunc "$@"

This is just the problem at hand, though. Other problems include not quoting your variables and using command expansion of ls, lst=(`ls $x`), instead of globs, lst=( "$x"/* )

Upvotes: 3

Related Questions