12

When we run a command the last argument is saved in _ which we can access:

$ echo $_

Doesn't sound like a terribly useful feature. So why bother? Are there any practical applications?

8
  • 3
    Note that in bash, $_ has several meanings. See Understand the meaning of `$_` Commented Apr 7 at 8:20
  • 4
    What counts as practical varies from person to person. I can easily imagine any use being dismissed as "oh, but that can be done with ... <insert other feature>"
    – muru
    Commented Apr 7 at 9:09
  • Interestingly, I thought Rosetta Code would prove instructive under the entry "Topic variable". There you'll find Perl, Ruby, Raku, and PowerShell all listed as using $_ for the "Topic variable". However UNIX Shell is listed as using $? as the "Topic variable". See: rosettacode.org/wiki/Topic_variable#UNIX_Shell Commented Apr 8 at 10:05
  • @jubilatious1, umh, the shell's $? has pretty much nothing to do with Perl's $_, or Python's _... $? is closer to errno in C. Those kinds of listings are always something to be taken with a grain of salt.
    – ilkkachu
    Commented Apr 8 at 17:46
  • 1
    @jubilatious1, I'm saying that the shell's $? has a lot more to do with C's errno, than with something like Perl's $_. The example there relies on awkwardly using the exit status to return the result of a computation. That's not a good idea to do, first, because the value range is really limited, and second, because the idea of the exit status is to tell if the command or function succeeded or failed.
    – ilkkachu
    Commented Apr 8 at 19:19

2 Answers 2

13

It has interactive uses, and can be exploited to perpetrate "code golfing".

It can reduce code by avoiding the need for a temporary variable, like:

temp=$destdir/$outfile
cp $infile $temp
chmod go-w $temp

to

cp $infile $destdir/$outfile
chmod go-w $_

I don't see this $_ feature among the Special Parameters of POSIX; it is a Bash extension (possibly in other shells).

It is a badly implemented hack, which breaks when you set a debug trap, as demonstrated by the following script:

#!/bin/bash

dbg()
{
  :
}

echo abc
echo $_

trap dbg debug

echo abc
echo $_

The output under Bash 4.4.20 is:

$ ./underscore.sh
abc
abc
abc
dbg

You can see that when we enable the debug trap, $_ no longer takes on the expected value abc after echo abc. In the specification of $_, "last command" literally refers to the most recently executed command, not the previous command in the command sequence.

You definitely don't want to be using this in any Bash program that anyone might ever want to debug with a debugger that is implemented with the help of the debug trap.

Interactive use of $_ is the same: refer to the last argument of the previous command. This raises the question: why would anyone use this instead of one of the commands M-_ or M-. which expand the same item into the command line?

The differences in $_ are that:

  • It is much more compact than the expansion of a long path.

  • When a command with $_ is recalled from history, it no longer refers to its own predecessor in history, but to whatever command was most recently executed. This can be exploited. We can recall and re-use a command that contains $_ to operate on the most recently used right argument, rather than to exactly repeat an old command with the same arguments.

  • The content produced by M. is based on the raw, unexpanded command line, whereas $_ produces the actual last argument of the previous command. We can show this difference like so:

    $ echo a{b,c}
    ab ac
    $ echo $_
    ac
    $ echo a{b,c}
    $ echo █
    

    At the point indicated by the cursor block , type the M. command. Meta M may be Esc or the Alt modifier. The result is:

    $ echo a{b,c}█
    

    In other words, the raw non-whitespace last token a{b,c} from the previous command is inserted, rather than the semantic item ac. This looks like more of a GNU Readline feature than a feature of GNU Bash.

13
  • 2
    I have to say that "code golfing" is the worst way to describe it. Is that really its only purpose? Not as a convenience shortcut or anything, just "code golfing"? Commented Apr 7 at 8:20
  • 2
    @u1686_grawity, interactively, it's not code golfing, it's keystroke saving. There are better alternatives than $_ for that though like line editor widgets that do the same or csh-style history expansion. For a start, that $_ (like all parameter expansions in bash) should be quoted ("$_"). Commented Apr 7 at 8:22
  • @u1686_grawity I think if you use this in a program, outside of a code golfing contest, you should be flogged with a wet noodle. For one thing, I seem to recall that it breaks under debugging. If you have a debug trap that executes commands after every command, it messes with $_. Also, $_ is not in POSIX; I'm looking at the spect and don't see it among the Special Parameters.
    – Kaz
    Commented Apr 7 at 8:32
  • Question is tagged bash so it's not really POSIX anyway Commented Apr 7 at 8:42
  • 1
    @ilkkachu I got mixed up reading the man page in bash. It's the first variable listed in a new section immediately after the Special Variables section.
    – Kaz
    Commented Apr 7 at 18:50
4

I use it often in the combo

mkdir verylongdirectoryname
cd $_
2
  • 4
    You could use Alt + . to insert last parameter (on emacs mode)
    – Pablo A
    Commented Apr 7 at 20:55
  • 1
    !$ also works. It also expands to the last parameter.
    – Tekno
    Commented Apr 9 at 6:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .