The question is published on by Tutorial Guruji team.
I just accidentally found out that in bash, we can assign a command into a variable without using alias
.
g=date $g Mon Jun 27 13:00:40 MYT 2016
That works. Here’s another example:
jj="ping yahoo.com" $jj PING yahoo.com (98.138.253.109) 56(84) bytes of data. 64 bytes from ir1.fp.vip.ne1.yahoo.com (98.138.253.109): icmp_seq=1 ttl=41 time=347 ms 64 bytes from ir1.fp.vip.ne1.yahoo.com (98.138.253.109): icmp_seq=2 ttl=41 time=345 ms 64 bytes from ir1.fp.vip.ne1.yahoo.com (98.138.253.109): icmp_seq=3 ttl=41 time=345 ms
I am using this version of bash bash --version
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
I have looked into stackexchange and tldp abs, but didn’t find we can do it like this though. So is this a new features of bash or something being overlooked ? Is this considered command substitution ?
Answer
This is expected behaviour and has been working for ages. It is useful for building up commands in scripts.
Say, for example, that I sometimes should apply decompression on some input before sending it into a pipeline (and compression on the output afterwards), but sometimes not. Using bash
:
if (( use_compression == 1 )); then infilter='gzip -d -c' outfilter='gzip -c' else infilter='cat' outfilter='cat' fi $infilter "$indatafile" | somepipeline | $outfilter >"$outdatafile"
Is it command substitution? No. “Command substitution” refers specifically to substituting $(...)
or the back-tick-variant with the contents of its output.
This is instead parameter expansion, i.e. simply replacing the parameters with their values. This happens before the command is actually executed which is why it works.
This means that stuff like the following works on the command line too:
$ decompress='gzip -d -c' $ ${decompress/g/gun/} filename >unzippedfilename
(that would execute gunzip
rather than gzip
)
EDIT: About aliases.
The bash
manual says:
For almost every purpose, aliases are superseded by shell functions.
… and I agree.
Aliases are good for short things like
alias ls="ls -F"
(that’s the only alias I have in my own shell sessions)
You probably don’t want to use parameter expansions for “aliasing” commands on the command line. If not for any other reason than it’s a pain in the neck to type. Parameter expansion also does not allow for doing slightly more complex tasks, such as pipelining.
If you have moderately complex operations that you are performing regularly, use shell functions for them instead.
Taking the example from the accepted answer to the U&L question (that you link to in the comments below):
alias my_File='ls -f | grep -v /'
This alias obviously works, but using
my_File='ls -f | grep -v /'
won’t work if you then try to use $my_File
as a command on the command line (as explained why in that U&L thread).
With a shell function, you will also be able to do things like pass arguments:
function my_File { ls -l "$@" | fgrep -v '/' } $ my_File -iF symlink 84416642 lrwxr-xr-x 1 kk staff 4 Jun 27 09:03 symlink@ -> file