Can I pass arguments to an alias command?

I want to know if I can pass an argument with an alias command.

for example:

alias d="dmesg | grep -iw usb | tail -5" 

Now d will print the last 5 lines. If I want to use d to print a different number of lines, I have to make change in the alias command declaration of d again.

Is there any way I can modify the declaration of an alias so that I don’t have to retype the declaration to change the number of lines. Like incorporating passing the number of lines as an argument while declaring alias for d? Or is there some other method to solve this?

Asked By: srk_cb


You need to have a function for this as described in the SO and here. Try the following:

foo() { /path/to/command "$@" ;}

and call the foo with:

foo arg1 arg2 arg3
Answered By: Ron

Aliases don’t take arguments. With an alias like alias foo='bar $1', the $1 will be expanded by the shell to the shell’s first argument (which is likely nothing) when the alias is run.

So: Use functions, instead.

d () {
  dmesg |grep -iw usb|tail -$num

num=${1:-5} uses the first argument, with a default value of 5 if it isn’t provided.

Then you can do:

$ d
# prints 5 lines
$ d 10
# prints 10 lines

Or, if you change the options you used slightly:

alias d="dmesg|grep -iw usb|tail -n 5"

Then you can pass additional -n options:

$ d
# prints 5 lines
$ d -n 10
# prints 10 lines

If multiple -n options are specified for tail, only the last is used.

Answered By: muru

Working around alias limitations with group command and here-string

Aliases can’t take arguments, but we can “simulate” that. Take for instance example of my answer on this question.

alias mkcd='{ IFS= read -r d && mkdir "$d" && cd "$d"; } <<<'

Key points that are happening here:

  • we use read built in to read a string into a variable d. Because we want to read a full string including blank characters(newline’s,tabs,spaces), we use IFS= and disable back backslash escapes with -r.
  • <<< which is here-string operator allows us to redirect whatever string we provide as argument to mkcd alias; the usage would be as mkcd "some directory"
  • multiple commands within alias are combined and executed in current shell using { list; } structure (which is known as group command in the bash manual). Note that leading space after { and ; individual list of commands are required.

In your specific example we could do:

alias d='{ IFS= read -r n; dmesg | grep -iw "usb" | tail -n ${n:-5};} <<<'

We could also make use of word splitting to store space-separated arguments:

bash-4.3$ { read -r a1 a2; echo "$a1"; echo "$a2";}  <<< "arg1 arg2"

Or we could use arrays to provide multiple arguments:

bash-4.3$ { read -a arr; echo "${arr[1]}"; echo "${arr[0]}";}  <<< "arg1 arg2"

But is this good approach ?

Not necessarily. The problem with such approach is that it’s very specific – arguments can’t be quoted easily which means we can only have arguments with no spaces.

bash-4.3$ { read -r a1 a2; echo "$a1"; echo "$a2";}  <<< "'arg1 with space' arg2"
with space' arg2

This is of course not something that would be widely used, simply because in the real world we have to deal with complex arguments, so this approach isn’t quite practical. Functions are far more flexible. And the need to quote args string becomes annoying fast.

Despite the limitations, this works with simple strings as arguments where we can afford word splitting, thus partially allows us to give arguments to aliases.

Answered By: Sergiy Kolodyazhnyy

In this particular case, where the parameters are at the end you don’t need a function, just:

alias d="dmesg | grep -iw usb | tail -n " 

Then run for eg. d 2 and you’ll get just two lines. The drawback is that there is no default value. To insert the parameter(s) in between I would follow this answer.

BTW, you can use journalctl parameters like --dmesg, -k -p err, etc.

Answered By: Pablo Bianchi
Categories: Answers Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.