Under Construction

Editing with fc

There is often a command in the history that needs to be slightly modified before it can be meaningfully re-executed in the current context. A file name may have to be adjusted, or an option has to be added or removed. With the bash history expansion very complex replacements are possible. However, you have to type in all the desired replacements without being able to see the result at the same time. With complex replacements, this often leads to errors and commands that were ultimately not wanted.

This is one of the strengths of the fc command: previous commands can be loaded into any editor (default is vi) and then corrected interactively in the editor before they are ultimately executed. The editor can be set via the variable FCEDITOR. If FCEDITOR is not set, the variable EDITOR is used. If this is not assigned either, the vi editor is used as the default.

We start with the following history:

[user01@aixe01 ~]$ history
    1  hostname
    2  pwd
    3  ls
    4  cd /etc
    5  ls -l
    6  cat passwd
    7  cd
    8  pwd
    9  ls -l log*
   10  tail log
   11  tail -30 log
   12  pwd
   13  cd /usr/bin
   14  find . -name "ta*"
   15  which tail
   16  id
   17  cd
   18  ls -l *.old
   19  rm file.old
   20  pwd
[user01@aixe01 ~]$

The command with the number 14 (‘find . -name “ta*”‘) should be executed again, but the search should now start at “/“. Using the bash history expansion mechanism, you could do this as follows:

!find:s/./\//

After pressing the ENTER key, the command is displayed briefly, but executed immediately (unless you use histverify).

With the help of the fc command, you can easily edit the previous command in an editor and only execute it once you have made all the desired changes:

[user01@aixe01 ~]$ fc find

The bash determines the last command that begins with the character string “find“, saves this command in a temporary file and then starts an editor. The user can now modify the command:

find . -name "ta*"
~

~
~
~
"/tmp//bash-fc.eM2Med" 1 line, 19 characters

After modifying, the result must be saved (otherwise the original command will be executed). When the editor is then exited, the fc command executes the command from the temporary file and then deletes the file:

[user01@aixe01 ~]$ fc find
find / -name "ta*"

/opt/freeware/bin/tabs
/opt/freeware/bin/tabs_32

[user01@aixe01 ~]$

Note: Running fc with no arguments, loads the last command into the editor!

Occasionally, when editing a previous command, it turns out that you don’t want to execute the command after all. However, in this case you should not exit the vi editor with “:q!“, since the temporary file then still contains the original command, which will then be executed.

If you do not want to execute a command, there are two options:

First: You force the editor to abort with an exit code different from 0, with vim you can do this with “:cq“. We’re not aware of an easy way to do this with vi.

Second: You simply delete the command in the editor or comment it out with a “#” and then exit the editor with save.

The editing mode described above also works with a range of commands! In the chapter Loading and Storing the History, we saved commands for rotating log files in the file logrotate_history. We now return to this example.

We load the history with the entries from the logrotate_history file:

[user01@aixe01 ~]$ history -r logrotate_history
[user01@aixe01 ~]$ history
    1  hostname
    2  pwd
    3  ls
    4  cd /etc
    5  ls -l
    6  cat passwd
    7  cd
    8  pwd
   9  ls -l log*
   10  tail log
   11  tail -30 log
   12  pwd
   13  cd /usr/bin
   14  find . -name "ta*"
   15  which tail
   16  id
   17  cd
   18  ls -l *.old
   19  rm file.old
   20  pwd
   21  ls /usr/bin/la*
   22  find / -name "ta*"
   23  mv log2 log3
   24  mv log1 log2
   25  mv log log1
   26  touch log
[user01@aixe01 ~]$

The commands to rotate are commands 23 through 26. By giving this range as an argument to fc,

[user01@aixe01 ~]$ fc 23 26

these 4 commands are loaded into the editor:

mv log2 log3
mv log1 log2
mv log log1
touch log
~

~
"/tmp//bash-fc.7E2Mek" 4 lines, 48 characters

Note: Of course you can still change one or more of the commands!

By saving and exiting the editor, the 4 commands are executed again:

[user01@aixe01 ~]$ fc 23 26
mv log2 log3
mv log1 log2
mv log log1
touch log
[user01@aixe01 ~]$

In contrast to the history expansion mechanism, the fc command can also be used to re-execute several commands (range of commands) in one operation.

With the help of the “-e” option you can specify an editor, which is then used instead of the standard editor (vi).