Basically, it's the last argument to the previous command.
!$
is the "end" of the previous command. Consider the following
example: We start by looking for a word in a file:
grep -i joe /some/long/directory/structure/user-lists/list-15
if joe is in that userlist, we want to remove him from it. We can either fire up vi with that long directory tree as the argument, or as simply as vi !$
Which
bash expands to:
vi /some/long/directory/structure/user-lists/list-15
(source; handy guide, by the way)
It's worth nothing the distinction between this !$
token and the special shell variable $_
.
Indeed, both expand to the last argument of the previous command. However, !$
is expanded during history expansion, while $_
is expanded during parameter expansion.
One important consequence of this is that, when you use !$
, the expanded command is saved in your history.
For example, consider the keystrokes
(The only characters changed are the $!
and $_
in the middle.)
In the former, when you press Up, the command line reads echo Foo Jar
, so the last line written to stdout is Foo Jar
.
In the latter, when you press Up, the command line reads echo $_ bar
, but now $_
has a different value than it did previously—indeed, $_
is now Jar
, so the last line written to stdout is Jar Jar
.
Another consequence is that _
can be used in other parameter expansions, for example, the sequence of commands
printf '%s ' isomorphism
printf '%s\n' ${_%morphism}sceles
prints isomorphism isosceles
.
But there's no analogous "${!$%morphism}
" expansion.
For more information about the phases of expansion in Bash, see the EXPANSION
section of man 1 bash
(this is called Shell Expansions in the online edition). The HISTORY EXPANSION
section is separate.
Create a wrapper shell function sshc
which prefixes the source ~/.bash_profile
boiler plate for you:
function sshc {
local host=$1
local cmd=$2
ssh $host "source ~/.bash_profile && $cmd"
}
You can then use this as:
$ sshc localhost 'which perl'
/home/calid/perl5/perlbrew/perls/perl-5.20.1/bin/perl
Best Answer
A backslash outside of quotes means “interpret the next character literally during parsing”. Since
.
is an ordinary character for the parser,\.
is parsed in the same way as.
, and invokes the builtin.
(of whichsource
is a synonym in bash).There is one case where it could make a difference in this context. If a user has defined an alias called
.
earlier in.profile
, and.profile
is being read in a shell that expands aliases (which bash only does by default when it's invoked interactively), then.
would trigger the alias, but\.
would still trigger the builtin, because the shell doesn't try alias expansion on words that were quoted in any way.I suspect that
.
was changed to\.
because a user complained after they'd made an alias for.
.Note that
\.
would invoke a function called.
. Presumably users who write functions are more knowledgeable than users who write aliases and would know that redefining a standard command in.profile
is a bad idea if you're going to include code from third parties. But if you wanted to bypass both aliases and functions, you could writecommand .
. The author of this snippet didn't do this either because they cared about antique shells that didn't have thecommand
builtin, or more likely because they weren't aware of it.By the way, defining any alias in
.profile
is a bad idea because.profile
is a session initialization script, not a shell initialization script. Aliases for bash belong in.bashrc
.