Why would my bash function supplement jokers for variables?

advertisements

In my ~/.bash_aliases:

function wtf (){
  echo $1;
}

Testing in bash:

>>  wtf t*
testes

WTF?


Now that I understand that bash is parsing my wildcard before passing it on, I thought I would share the function that I was building. Here's the final version of my recursive delete shortcut:

# delete recursively
function rmr () {
    find . -name "$1" -type f -delete -exec \
    echo $(tput setaf 1)"deleted >"$(tput setaf 2) {} \; ;
    l;
}


because you have a file called testes, and bash replaces t* with that before passing arguments to wtf(). You may have several files starting with t, but testes is the first, and wtf only echoes $1. If you replace $1 with $* you will see all of them.

E.g., if you have files testes and tumble (and no other file starting with t), and issue

wtf t*

bash will replace t* with testes tumble (space-separated) and then evaluate the line

wtf testes tumble

which will cause wtf to be passed testes as $1 and tumble as $2.

If you don't want the shell to do filename expansion, you have to put quotes around your argument, like wtf 't*' or wtf "t*". Single quotes have the advantage of not only avoiding filename expansion, put also any other kind of expansion (e.g. parameter expansion and variable expansion). Filename (or pathname) expansion happens with *, ? (among others), parameter and variable expansion with $.

For the same reason, you must quote the argument of echo, this time in double quotes, because you want parameter expansion of $1 to happen, but don't want (again!) filename expansion to happen:

function wtf() {
  echo "$1"
}

man bash is your friend, there is a lot to learn.

Within man bash, type /^EXPANSION or /Pathname Expansion. See also /^QUOTING.