39

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?

1
  • In (t)csh, "\!*" references arguments to an alias (the backslash is just to escape the exclamation mark which normally means "history"), and you can even reference individual arguments, though I don't remember how. So perhaps "tail -n \!*" or something (I don't think \!* will work with a minus sign immediately before it). However, not sure if this will work in (ba)sh.
    – user11553
    May 21, 2015 at 14:19

4 Answers 4

46

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 () {
  num=${1:-5}
  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.

3
  • 4
    For the functionally challenged like myself :) it might be helpful to briefly state where to put the function... ie ~/.bashrc or rc.local or wherever? Feb 13, 2017 at 4:47
  • @WinEunuuchs2Unix wherever the alias would have been put.
    – muru
    Feb 13, 2017 at 4:47
  • You add your aliases in the ~/.bash_aliases file. (Via: help.ubuntu.com/community/TransmissionHowTo#Bash_Aliases)
    – its_me
    Nov 7, 2021 at 1:24
12

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
7

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"
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"
arg2
arg1

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"
'arg1
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.

1

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .