325

How do I pass the command line arguments to an alias? Here is a sample:

alias mkcd='mkdir $1; cd $1;'

But in this case the $xx is getting translated at the alias creating time and not at runtime. I have, however, created a workaround using a shell function (after googling a little) like below:

function mkcd(){
  mkdir $1
  cd $1
}

Just wanted to know if there is a way to make aliases that accept CL parameters.
BTW - I use 'bash' as my default shell.

codeforester
  • 39,467
  • 16
  • 112
  • 140
Vini
  • 8,299
  • 11
  • 37
  • 49
  • 2
    O/T but about as an alternative to doing a mkcd function, you can write `mkdir mydirectoryname && cd $_` – moala Jul 01 '18 at 10:50

11 Answers11

343

Just to reiterate what has been posted for other shells, in Bash the following works:

alias blah='function _blah(){ echo "First: $1"; echo "Second: $2"; };_blah'

Running the following:

blah one two

Gives the output below:

First: one
Second: two
Thomas Bratt
  • 48,038
  • 36
  • 121
  • 139
  • 6
    Great solution. Some questions from a bash novice: Does the function have to be named with an underscore (or differently at all) or is that just for readability? What is the purpose of the trailing ";_blah" in defining the function? Why does it not work when using double quotes in place of single quotes (the $1 is not interpreted correctly) even when doing something that does not require quotes around the $1? Thanks in advance for the advice. I have a working solution but always like to understand more on why it works. – mynameispaulie Nov 11 '14 at 22:08
  • 4
    @mynameispaulie The function can be named anything. I've used an an underscore prefix as it is a common trick to help prevent name collisions (ie another function with the same name) – Thomas Bratt Nov 13 '14 at 16:00
  • 2
    @mynameispaulie With regards to the the trailing `;_blah`: The semi-colon is to finish the statement that defines the function. The `_blah` which follows the semicolon is the actual function being called when the alias is run. It might help to understand that When the alias is executed, a function is defined (or redefined if previously run) and then it is actually called. – Thomas Bratt Nov 13 '14 at 16:05
  • 8
    @mynameispaulie The double quotes allow `Bash` to replace `$1` and `$2` with the parameters passed to the function. Single quotes tell Bash not to do this. – Thomas Bratt Nov 13 '14 at 16:06
  • 5
    I see this alias/function combo copy/pasted a lot, but it does not seem to serve any useful purpose. The standard approach would be to define the function once, with a sane name, and not have an alias. – tripleee Mar 03 '16 at 14:51
  • 18
    I fail to see how this is preferred over `function blah(){ echo "First: $1"; echo "Second: $2"; }` – René Nyffenegger Apr 24 '16 at 13:38
  • 1
    @RenéNyffenegger the question asked for an alias – Thomas Bratt May 08 '16 at 08:55
  • 1
    great solution and it can even be used with embedded arguments - see following example : alias gitshow='function _blah(){ git show "$(git annotate $1 | grep $2 | head -1| cut -f1)"; };_blah' -- try it like this: gitshow – serup Jul 14 '16 at 08:14
  • 1
    Also usable directly after equal sign like =$1. For Example my grep except alias `alias greex='function _grepExcept(){ grep -R --exclude-dir=$1 $2 .; };_grepExcept'`. – MonTea Mar 24 '18 at 00:36
  • 1
    It looks like the spaces are necessary. I did not realize that at first. – Pro Q May 22 '18 at 19:50
  • 1
    Just for shorter command - we can drop the `function` ie `alias blah='_blah(){ echo "First: $1"; echo "Second: $2"; };_blah'` – Nam G VU Dec 03 '20 at 05:29
  • Great solution! Make sure you keep track of single quotes and double quotes. – Vaibhav Ranglani Nov 30 '21 at 05:44
  • [Why would I create an alias which creates a function?](https://stackoverflow.com/questions/57239089/why-would-i-create-an-alias-which-creates-a-function) (TLDR: probably don't). – tripleee Jun 01 '22 at 05:01
184

You found the way: create a function instead of an alias. The C shell has a mechanism for doing arguments to aliases, but bash and the Korn shell don't, because the function mechanism is more flexible and offers the same capability.

Charlie Martin
  • 110,348
  • 25
  • 193
  • 263
  • 1
    You however don't need functions when creating aliases in `.bashrc` file. For example # create an alias that takes port-number by the user alias serve="python -m SimpleHTTPServer $1" After making the change in the .bashrc file, make sure you enter the following command. ~$ source .bashrc You should be able to use this like so ~$ serve 8998 – kaizer1v Nov 10 '17 at 03:46
  • 8
    @kaizer1v, My observation on CentOS7.3 bash version 4.2.46 is that your suggestion doesn't work as you think it does. Because you are using double quotes the $1 is actually being evaluated to an empty string and the alias is actually the same as alias serve="python -m SimpleHTTPServer" and so whatever you pass after that alias is ALSO passed on the command line. If you try this set -x; alias serve="python -m SimpleHTTPServer $1 &" you will see the error/problem. Both your argument and the alias command are run as separate commands. – PatS Feb 13 '18 at 17:33
  • Functions do NOT offer the same capability as aliases. Aliases can be generated inside of a code block and affect surrounding structures (breaking from a while loop, starting a do block but not ending it, etc). I use this mechanism extensively to support elegant exception handling and trace logging in bash that could never be done with functions. Alias needs to be able to take parameters also to fully unlock it's potential. – Jeremy Gurr Nov 24 '21 at 15:52
61

You cannot in ksh, but you can in csh.

alias mkcd 'mkdir \!^; cd \!^1'

In ksh, function is the way to go. But if you really really wanted to use alias:

alias mkcd='_(){ mkdir $1; cd $1; }; _'
Sanjaya R
  • 6,246
  • 2
  • 17
  • 19
  • As an interesting side note, I think that the remote code execution vulnerability that everybody's been talking about recently involves doing almost exactly this same thing, but in an environment variable being set by raw user input. http://www.openwall.com/lists/oss-security/2014/09/24/11 – Floegipoky Sep 25 '14 at 13:41
  • 1
    @Floegipoky - Because its in an alias and not an env var, its substantially different. The ShellShock issues is that it runs when the env var is set. Setting an env var is supposed to be a safe operation. No script executes when the above alias is set, only when the alias is run. – Sanjaya R Sep 26 '14 at 17:11
  • Perhaps it should be pointed out that `csh` is usually not what a modern person should want to use. The alias-which-creates-a-function-then-executes-that-function indirection is relatively popular, but offers no benefit over a proper function as far as I can tell. (The function should properly quote its argument, anyway.) Downvoting. – tripleee Sep 13 '16 at 13:31
19

To quote the bash man page:

There is no mechanism for using arguments in the replacement text. If arguments are needed, a shell function should be used (see FUNCTIONS below).

So it looks like you've answered your own question -- use a function instead of an alias

Chris Dodd
  • 2,920
  • 15
  • 10
14

You may also find this command useful:

mkdir dirname && cd $_

where dirname is the name of the directory you want to create

dciccale
  • 442
  • 6
  • 12
8

The easiest way, is to use function not alias. you can still call a function at any time from the cli. In bash, you can just add function name() { command } it loads the same as an alias.

function mkcd() { mkdir $1; cd $1 ;}

Not sure about other shells

Luke Attard
  • 161
  • 1
  • 4
  • The `function` keyword is permitted by Bash (and Ksh) but doesn't really serve any useful purpose here. The portable syntax is simply `mkcd () { mkdir "$1"; cd "$1"; }` (notice also the [fixed quoting](https://stackoverflow.com/questions/10067266/when-to-wrap-quotes-around-a-shell-variable)). – tripleee Jun 01 '22 at 05:00
4

I found that functions cannot be written in ~/.cshrc file. Here in alias which takes arguments

for example, arguments passed to 'find' command

alias fl "find . -name '\!:1'"     
Ex: >fl abc

where abc is the argument passed as !:1

pevik
  • 4,523
  • 3
  • 33
  • 44
  • 4
    That's not useful for the OP, whose default shell is bash. And Sanjaya R's answer mentioned csh aliases 4 years ago. – Keith Thompson Jun 18 '13 at 19:50
  • 1
    Sanjaya R's answer didn't explain what `!:1` meant. I had to scroll down to see here that it was the argument. A good answer doesn't leave more questions, even if it wasn't for the OPs shell type. – searchengine27 Jan 31 '17 at 00:54
2

You actually can't do what you want with Bash aliases, since aliases are static. Instead, use the function you have created.

Look here for more information: http://www.mactips.org/archives/2008/01/01/increase-productivity-with-bash-aliases-and-functions/. (Yes I know it's mactips.org, but it's about Bash, so don't worry.)

samoz
  • 56,849
  • 55
  • 141
  • 195
1

This works in ksh:

$ alias -x mkcd="mkdir \$dirname; cd \$dirname;"
$ alias mkcd
mkcd='mkdir $dirname; cd $dirname;'
$ dirname=aaa 
$ pwd
/tmp   
$ mkcd
$ pwd
/tmp/aaa

The "-x" option make the alias "exported" - alias is visible in subshells.

And be aware of fact that aliases defined in a script are not visible in that script (because aliases are expanded when a script is loaded, not when a line is interpreted). This can be solved with executing another script file in same shell (using dot).

-4

Here's a simple example function using Python. You can stick in ~/.bashrc.

You need to have a space after the first left curly bracket.

The python command needs to be in double quotes to get the variable substitution. Don't forget that semicolon at the end.

count(){ python -c "for num in xrange($1):print num";}

Example run:

$ count 6
0
1
2
3
4
5
$
tripleee
  • 175,061
  • 34
  • 275
  • 318
AAAfarmclub
  • 2,202
  • 1
  • 19
  • 13
  • In modern Python, you want `range` instead of `xrange`. But there is no need for Python here; just `printf '%s\n' {0..5}` or `for ((i=0; i<$1; ++i)) do; echo "$i"; done` if you want to use a variable for the end of the range. – tripleee Jun 01 '22 at 05:05
  • My post didn't answer the question, but it was supposed to just be a simple example that creates a function at the command line, uses Python, and takes an argument. – AAAfarmclub Jun 02 '22 at 08:54
  • Interpolating into a double-quoted string is brittle at best; perhaps better then to write a Python script which reads the argument from `sys.argv[1]` ... but again, there is no particular reason to use Python (or Awk, or COBOL, or Smalltalk, or C) here. – tripleee Jun 02 '22 at 09:29
-6

An empty alias will execute its args:

alias DEBUG=
  • 17
    I see by your rep that you are new to SO (Stack Overflow). Please don't be dismayed by the voting down of your answer. It has been voted down because it really doesn't answer the question that the OP (Original Poster) asked to have answered. Hang in their and keep trying. Also when answering, try to include a simple example of how your answer works and show the output. This will help others see how your answer works. – PatS Feb 13 '18 at 17:24