1

I'm trying to insert an argument in the middle of a command with "$@" for learning purposes. I don't know if that's optimal, but it's what I've been trying to do. This is what I have: when I run test.sh foo it runs echo "$@" bar which I was hoping would print foo bar. Instead, it's printing bar foo. I don't know neither if that's expected behavior nor what I should do instead.

test.sh foo
# runs
echo "$@" bar
# which is printing
bar foo

Edit: I had simplified the context and was in reality trying to use "$@" in an alias.

AdminBee
  • 22,803
  • 1
    What does test.sh actually contain? If it really contained echo "$@" bar, the output of running ./test.sh foo would be foo bar. Note that test.sh foo doesn't look for test.sh in the current directory unless you've added . to PATH. Maybe you have another test.sh somewhere else and you're running that? – Gilles 'SO- stop being evil' Jul 28 '21 at 21:51
  • @Gilles'SO-stopbeingevil' Okay, so I'll be more specific. If I'm setting up an alias test='echo "$@" bar' and I run test foo in a terminal, it prints bar foo. – matticebox Jul 28 '21 at 21:55
  • 2
  • 2
    Aliases don't take arguments into $@, just whatever you stick after the alias name ends up at after the expansion, so you end up with echo "$@" bar foo. – ilkkachu Jul 28 '21 at 22:00
  • @ilkkachu I see. So, asking as a newbie, a function would be an ideal alternative to what I'm trying to do? – matticebox Jul 28 '21 at 22:14

1 Answers1

2

Aliases are just a simple replacement, they don't take arguments themselves. So if you have alias x='echo "$@" bar'(*), and you run x foo, you end up with

echo "$@" bar foo

i.e. with just the alias name x replaced with the contents and the rest left on in the end. Now, that "$@" is the argument list of the context where x foo was run. Probably your interactive shell, which usually doesn't have anything in the argument list, so the "$@" gets removed. But if you had something in the argument list (positional parameters), they'd be expanded at that position:

$ alias x='echo "$@" bar'
$ set -- args here
$ x foo
args here bar foo

Instead, if you used a function or a script file, that would work. This should print foo bar:

f() {
    echo "$@" bar
}
f foo

as should running something like ./s.sh foo, if s.sh is executable and contains that echo line.

See:

(* test is a standard command, the same as [ .. ], so better not use it for... well, this kind of testing purposes.)

ilkkachu
  • 138,973