For bash script, I can use "$@"
to access arguments. What's the equivalent when I use an alias?
6 Answers
Alias solution
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
This creates a temporary function f
, which is passed the arguments.
Alias arguments are only passed at the end. Note that f
is called at the very end of the alias.
The unset -f
removes the function definition as the alias is executed so it doesn't hang around afterwards.
-
1I had
f
aliased. Once I unaliasedf
it works fine. The old name collision thing. Dec 19, 2017 at 3:51 -
2
-
2
-
2This is great for special cases. Consider a block of code where you want to prevent echo with minimal fuss:
alias echo='f(){ echo "$@" &>/dev/null; unset -f f; }; f'
. For example, adding that one line to a boot script to force a quiet mode.– BeejorMay 2, 2019 at 20:03 -
This looks like a useless complication that still has many of the downsides of an alias, like the quoting hell that comes up if the function code itself needs to use single-quoted strings. Just defining the function the usual way wouldn't suffer that problem, and
wrap_args(){ echo before "$@" after; };
would be shorter to boot, and there wouldn't be name clashes with the temporary function...– ilkkachuNov 27, 2022 at 17:05
Aliases don't take arguments. They work more or less like simple text replacement, meaning all words after the alias (the ones that look like "arguments" to the alias) just get left at the end of the expanded alias.
For instance, if you were to alias ls
to ls -la
, then typing ls foo bar
would really execute ls -la foo bar
on the command line. Which is probably fine in that example, but if foob
is an alias to foo | bar
, then foob abc def
expands to foo | bar abc def
, and there's no way to arrange those two words to be used as arguments to the left-hand side of the pipeline.
One might attempt changing the alias to something like foo "$@" | bar
or so, but that would expand to foo "$@" | bar abc def
and use the positional parameters of the outer context in the expansion of "$@"
. That's probably not what you want.
If you want to have actual control over how the arguments are interpreted, then you could write a function like so:
my_program_wrapper() {
local first_arg=$1 \
second_arg=$2
shift 2 # get rid of the first two arguments
# ...
/path/to/my_program "$@"
}
-
4opengroup.org/onlinepubs/009695399/utilities/… Functions in
sh
are definedmy_program_wrapper() { ...; }
. Bash does handle the keywordfunction
but why not go with what's more portable? Nov 5, 2010 at 1:51 -
Do you have to export the function for it to be available as an interactive shell executable? Oct 13, 2022 at 18:48
-
1@SridharSarnobat If by export you mean
export -f my_program_wrapper
see this question for an explanation, then the answer is no; you will want to add the function to~/.bashrc
in order to have it usable in interactive shells. Oct 18, 2022 at 22:30
Adding to the present answers, an important thing to realize about how aliases work is that all the parameters you type after an aliased command will be used literally at the end. So there is no way to use alias for two commands (piped or not), out of which the first should interpret the parameters. To make it clear, here's an example of something that would not work as expected:
alias lsswp="ls -l | grep swp"
(an example inspired by this question) this will always use the output of ls -l
performed in the current directory and do a grep on that - so using
lsswp /tmp/
would be equivalent to ls -l | grep swp /tmp/
and not ls -l /tmp/ | grep swp
.
For all purposes where the arguments should be used somewhere in the middle, one needs to use a function instead of an alias.
-
plus one,
alias lsswp='ls -l | grep swp'
with single quote is also working on unix.– TimoApr 16, 2022 at 10:21
You don't have to do anything, actually; aliases do this automatically. For instance:
$ alias less="less -eirqM"
$ less foo.txt
You will see foo.txt's first page, and less
will quit at EOF (-e), searches will be case-insensitive (-i), etc.
-
Can you please look at my question - none of the solutions works for me and I am not allowed start a bounty.– JJDFeb 9, 2016 at 23:40
-
1@JJD The one who answered your question is correct: you want a function in that case, not an alias. Since the accepted answer to this question is essentially the same, your question was rightly closed. Feb 9, 2016 at 23:44
I'm answering for csh:
Yes, you can use the parameters in aliases and - as a difference to what has been said above - you can refer to them anywhere in the definition of alias - not only at the end.
Example for tar-gz -ing something:
$ alias tgz "tar cvf - \!:1 | gzip -9 > \!:2.tar.gz"
, where !:1
and !:2
are the parameters you will supply when calling your alias.
Example of use:
$ ls
clrcf.dat user_comment_2016.06.03_12:51:50.txt user_comment_2016.06.03_12:54:48.txt
TEST-wADM.tec user_comment_2016.06.03_12:52:04.txt user_comment_2016.06.03_12:55:13.txt
$ tgz user* out
a user_comment_2016.06.03_12:51:50.txt 1K
a user_comment_2016.06.03_12:52:04.txt 1K
a user_comment_2016.06.03_12:54:48.txt 1K
a user_comment_2016.06.03_12:55:13.txt 1K
$ ls out*
out.tar.gz
Which effectively means that you used two parameters that you inserted at arbitrary places of the tar command, making of all of it an alias tgz
-
I used to use csh exclusively, but since bash was always default I had to gave up and use bash.. This is one of the features from csh that I miss, I was struggling to reproduce it in bash. I guess there is no direct equivalent in bash, and that the best (only) alternative is to use a function. Apr 20, 2021 at 0:05
This example, to pretty print a markdown file in the terminal, is working if the first command of the pipe is able to read from stdin:
alias mdcat='(pandoc | lynx -stdin -dump) <'
So mdcat myfile.md
can then be used instead of pandoc myfile.md | lynx -stdin -dump
.
This is not exactly answering your question, as it does not make "$@" available in the alias, but it probably answers some real-world usecases for this question.
-
1The (almost) equivalent function definition,
mdcat() (pandoc < "$1" | lynx -stdin -dump)
, would still be (barely) shorter. Though one probably would usemdcat() { pandoc < "$1" | lynx -stdin -dump; }
anyway, as the subshell is unnecessary. Though in the case of the alias, the whole pipeline wouldn't start if one neglected to give the filename (as the plain<
at end of line would be a syntax error), but the function would still startlynx
on the right-hand side of the pipeline, even if the redirection on the left side failed. So in a way, that might be seen an advantage for the alias.– ilkkachuNov 27, 2022 at 17:11