How many times have you typed a long command and quickly pressed enter, only to find out that you misspelled something or missed an argument?
As a CLI user, you probably look to minimize the number of actions it takes to get a task done - so instead of rewriting the entire command (or arrowing up and changing the string), you can easily replace a string in your command with builtin bash tools.
Event Designators: Quick Substitutions
An event designator is a reference to a command line entry in the history list.
The quick substitution is performed by using the following syntax:
^str1^str2^, which means that the last command will be run again with
str1 replaced with
str2. Let’s see an example - say I want to copy a file named
file1.py to the current directory:
$ cp ~/foo/bar/fle1.py .
Oops, I misspelled
file1.py and wrote
fle1.py. I can easily rerun the command with the correct file name using quick substitution:
Pressing enter prints the corrected command to the standard output and runs it as intended! You should note that the only the first matching string is replaced. There are ways to perform global replace, but the syntax is quite arcane and easy to forget. However, there is an alternative, which brings us to the next builtin.
By the way, the quote above is taken from the
man pages. You should look it up (it is generally a good idea to read
man once in while).
fc: memorable substitution and much more
Another builtin way to perform quick substitution is with the
fc command (the name can be thought of as a mnemonic for ‘fix command’).
To perform the same substitution from the previous example, run:
$ fc -s fle=file
This can be easily aliased to become even more comfortable:
$ alias r="fc -s" $ r fle=file
I find this much more memorable than the
Do note that this command performs a global substitution, so you have to be more careful about it.
Editing previous command
fc can do much more. Sometimes a simple substitution is not enough to fix the command. For example, when running a long
curl command with payload, and you need to change some of the payload’s values.
Arrowing up and editing in the command line feels really inefficient, especially if you are a vim user. Yeah, I could copy the command to vim, make the changes, copy it again to the command line and run it. But that’s an awful lot of steps for such a simple task. Well, this paragraph does not reside under the
fc title for nothing! Try running the following:
Yes, it does exactly what we needed it to (or maybe it opened nano, but we can fix that if needed)! Running
fc with no flags or arguments, opens up the previous command to edit in a predefined editor. Edit, save and exit and the fixed command will be run!
Changing the editor
For one time (or always by aliasing and saving in
$ fc -e ename
ename is the name of the desired editor.
Another option is to define the environment variable FCEDIT with the desired editor. For vim that would be:
$ export FCEDIT=vim
Aborting the fix and avoiding unwanted re-reruns
You will notice that even if you don’t save the changes and quit the editor (
:q! in vim), the unedited command will be executed, which is probably not what you want.
To avoid that, the editor must return a non-zero exit code. You can do this in vim by exiting with
:cq! if you made changes).
These are just very few ways to fix previously executed commands in bash. There are of course others (such as the more known event designator
What are your favorites? Please write them in the comments!