Create an alias that takes a file name as a paremeter, removes the extension of the parameter and creates a new extension [duplicate]
Solution 1:
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.
Solution 2:
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
Solution 3:
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 variabled
. Because we want to read a full string including blank characters(newline's,tabs,spaces), we useIFS=
and disable back backslash escapes with-r
. -
<<<
which is here-string operator allows us to redirect whatever string we provide as argument tomkcd
alias; the usage would be asmkcd "some directory"
- multiple commands within alias are combined and executed in current shell using
{ list; }
structure (which is known asgroup command
in thebash
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.