29

The install guide for ack suggests installing the ack script using this command:

curl http://beyondgrep.com/ack-2.14-single-file > ~/bin/ack && chmod 0755 !#:3 

I assume that the !#:3 at the end is some kind of back-reference, but what does it mean? Is there an equivalent in zsh? Google has not been helpful.

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
Matt Pfefferle
  • 675
  • 1
  • 6
  • 10
  • 1
    It means my cat walked across the keyboard at a really bad time. – IQAndreas Oct 16 '15 at 01:52
  • @IQAndreas: Well, it's a valid command, so your cat must be clever enough to defeat the [cat typing detector](http://lifehacks.stackexchange.com/questions/9531/how-can-i-keep-my-cat-off-my-keyboard).  Clearly this is not a useless cat.  :-)  ⁠ – G-Man Says 'Reinstate Monica' Oct 16 '15 at 05:27

2 Answers2

33

This is a special syntax, expanded by bash. It also works for zsh.

According to the bash man page (section HISTORY EXPANSION), the pattern expands as following:

  • The event designator !# refers to the entire command line typed so far which is curl http://beyondgrep.com/ack-2.14-single-file > ~/bin/ack && chmod 0755
  • : splits between the event designator (this case the entire line) and the word designator (selects a sub-part)
  • the word designator 3 which selects the third word/argument (counting of words starts at zero), in this case ~/bin/ack.

The final command line (usually displayed before executed) is: curl http://beyondgrep.com/ack-2.14-single-file > ~/bin/ack && chmod 0755 ~/bin/ack.

For details, see the bash manual or very similar the zsh manual

jofel
  • 26,513
  • 6
  • 65
  • 92
  • 8
    I can't help but wonder: who thought this feature would ever be a good idea? – Rhymoid Oct 15 '15 at 20:03
  • 3
    @Rhymoid, I don't use `!#` much, but `!!`, `!$`, `!*`, `!sud:p` and many others are all extremely useful and I use them all the time. Check out http://unix.stackexchange.com/a/67/135943 – Wildcard Oct 16 '15 at 05:37
11

In bash, it is history substitution (all history substitutions start with !). Specifically, !# means everything on the command line so far, and the addition ':3' means the third word (starting count at 0).

So, the above command translates !#:3 into ~/bin/ack.

heemayl
  • 54,820
  • 8
  • 124
  • 141
Brian
  • 1,442
  • 1
  • 10
  • 13