Make a Bash alias that takes a parameter?

后端 未结 20 1960
长发绾君心
长发绾君心 2020-11-21 06:53

I used to use CShell (csh), which lets you make an alias that takes a parameter. The notation was something like

alias junk=\"mv \\\\!* ~/.Trash\"

相关标签:
20条回答
  • 2020-11-21 06:58

    Here's the example:

    alias gcommit='function _f() { git add -A; git commit -m "$1"; } ; _f'
    

    Very important:

    1. There is a space after { and before }.
    2. There is a ; after each command in sequence. If you forget this after the last command, you will see > prompt instead!
    3. The argument is enclosed in quotes as "$1"
    0 讨论(0)
  • 2020-11-21 07:01

    Refining the answer above, you can get 1-line syntax like you can for aliases, which is more convenient for ad-hoc definitions in a shell or .bashrc files:

    bash$ myfunction() { mv "$1" "$1.bak" && cp -i "$2" "$1"; }
    
    bash$ myfunction original.conf my.conf
    

    Don't forget the semi-colon before the closing right-bracket. Similarly, for the actual question:

    csh% alias junk="mv \\!* ~/.Trash"
    
    bash$ junk() { mv "$@" ~/.Trash/; }
    

    Or:

    bash$ junk() { for item in "$@" ; do echo "Trashing: $item" ; mv "$item" ~/.Trash/; done; }
    
    0 讨论(0)
  • 2020-11-21 07:03

    If you're looking for a generic way to apply all params to a function, not just one or two or some other hardcoded amount, you can do that this way:

    #!/usr/bin/env bash
    
    # you would want to `source` this file, maybe in your .bash_profile?
    function runjar_fn(){
        java -jar myjar.jar "$@";
    }
    
    alias runjar=runjar_fn;
    

    So in the example above, i pass all parameters from when i run runjar to the alias.

    For example, if i did runjar hi there it would end up actually running java -jar myjar.jar hi there. If i did runjar one two three it would run java -jar myjar.jar one two three.

    I like this $@ - based solution because it works with any number of params.

    0 讨论(0)
  • 2020-11-21 07:04

    Both functions and aliases can use parameters as others have shown here. Additionally, I would like to point out a couple of other aspects:

    1. function runs in its own scope, alias shares scope

    It may be useful to know this difference in cases you need to hide or expose something. It also suggests that a function is the better choice for encapsulation.

    function tfunc(){
        GlobalFromFunc="Global From Func" # Function set global variable by default
        local FromFunc="onetwothree from func" # Set a local variable
    
    }
    
    alias talias='local LocalFromAlias="Local from Alias";  GlobalFromAlias="Global From Alias" # Cant hide a variable with local here '
    # Test variables set by tfunc
    tfunc # call tfunc
    echo $GlobalFromFunc # This is visible
    echo $LocalFromFunc # This is not visible
    # Test variables set by talias
    # call talias
    talias
    echo $GlobalFromAlias # This is invisible
    echo $LocalFromAlias # This variable is unset and unusable 
    

    Output:

    bash-3.2$     # Test variables set by tfunc
    bash-3.2$     tfunc # call tfunc
    bash-3.2$     echo $GlobalFromFunc # This is visible
    Global From Func
    bash-3.2$     echo $LocalFromFunc # This is not visible
    
    bash-3.2$     # Test variables set by talias
    bash-3.2$     # call talias
    bash-3.2$     talias
    bash: local: can only be used in a function
    bash-3.2$     echo $GlobalFromAlias # This is invisible
    Global From Alias
    bash-3.2$ echo $LocalFromAlias # This variable is unset and unusable
    

    2. wrapper script is a better choice

    It has happened to me several times that an alias or function can not be found when logging in via ssh or involving switching usernames or multi-user environment. There are tips and tricks with sourcing dot files, or this interesting one with alias: alias sd='sudo ' lets this subsequent alias alias install='sd apt-get install' work as expect (notice the extra space in sd='sudo '). However, a wrapper script works better than a function or alias in cases like this. The main advantage with a wrapper script is that it is visible/executable for under intended path (i.e. /usr/loca/bin/) where as a function/alias needs to be sourced before it is usable. For example, you put a function in a ~/.bash_profile or ~/.bashrc for bash, but later switch to another shell (i.e. zsh) then the function is not visible anymore. So, when you are in doubt, a wrapper script is always the most reliable and portable solution.

    0 讨论(0)
  • 2020-11-21 07:07

    Bash alias absolutely does accept parameters. I just added an alias to create a new react app which accepts the app name as a parameter. Here's my process:

    Open the bash_profile for editing in nano

    nano /.bash_profile
    

    Add your aliases, one per line:

    alias gita='git add .'
    alias gitc='git commit -m "$@"'
    alias gitpom='git push origin master'
    alias creact='npx create-react-app "$@"'
    

    note: the "$@" accepts parameters passed in like "creact my-new-app"

    Save and exit nano editor

    ctrl+o to to write (hit enter); ctrl+x to exit

    Tell terminal to use the new aliases in .bash_profile

    source /.bash_profile
    

    That's it! You can now use your new aliases

    0 讨论(0)
  • 2020-11-21 07:08

    TL;DR: Do this instead

    Its far easier and more readable to use a function than an alias to put arguments in the middle of a command.

    $ wrap_args() { echo "before $@ after"; }
    $ wrap_args 1 2 3
    before 1 2 3 after
    

    If you read on, you'll learn things that you don't need to know about shell argument processing. Knowledge is dangerous. Just get the outcome you want, before the dark side forever controls your destiny.

    Clarification

    bash aliases do accept arguments, but only at the end:

    $ alias speak=echo
    $ speak hello world
    hello world
    

    Putting arguments into the middle of command via alias is indeed possible but it gets ugly.

    Don't try this at home, kiddies!

    If you like circumventing limitations and doing what others say is impossible, here's the recipe. Just don't blame me if your hair gets frazzled and your face ends up covered in soot mad-scientist-style.

    The workaround is to pass the arguments that alias accepts only at the end to a wrapper that will insert them in the middle and then execute your command.

    Solution 1

    If you're really against using a function per se, you can use:

    $ alias wrap_args='f(){ echo before "$@" after;  unset -f f; }; f'
    $ wrap_args x y z
    before x y z after
    

    You can replace $@ with $1 if you only want the first argument.

    Explanation 1

    This creates a temporary function f, which is passed the arguments (note that f is called at the very end). The unset -f removes the function definition as the alias is executed so it doesn't hang around afterwards.

    Solution 2

    You can also use a subshell:

    $ alias wrap_args='sh -c '\''echo before "$@" after'\'' _'
    

    Explanation 2

    The alias builds a command like:

    sh -c 'echo before "$@" after' _
    

    Comments:

    • The placeholder _ is required, but it could be anything. It gets set to sh's $0, and is required so that the first of the user-given arguments don't get consumed. Demonstration:

      sh -c 'echo Consumed: "$0" Printing: "$@"' alcohol drunken babble
      Consumed: alcohol Printing: drunken babble
      
    • The single-quotes inside single-quotes are required. Here's an example of it not working with double quotes:

      $ sh -c "echo Consumed: $0 Printing: $@" alcohol drunken babble
      Consumed: -bash Printing:
      

      Here the values of the interactive shell's $0 and $@ are replaced into the double quoted before it is passed to sh. Here's proof:

      echo "Consumed: $0 Printing: $@"
      Consumed: -bash Printing:
      

      The single quotes ensure that these variables are not interpreted by interactive shell, and are passed literally to sh -c.

      You could use double-quotes and \$@, but best practice is to quote your arguments (as they may contain spaces), and \"\$@\" looks even uglier, but may help you win an obfuscation contest where frazzled hair is a prerequisite for entry.

    0 讨论(0)
提交回复
热议问题