Configuration Information [Automatically generated, do not change]: Machine: x86_64 OS: linux-gnu Compiler: gcc Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-redhat-linux-gnu' -DCONF_VENDOR='redhat' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -I. -I. -I./include -I./lib -D_GNU_SOURCE -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic uname output: Linux sheep.uk.oracle.com 2.6.24.3-12.fc8 #1 SMP Tue Feb 26 14:21:30 EST 2008 x86_64 x86_64 x86_64 GNU/Linux Machine Type: x86_64-redhat-linux-gnu
Bash Version: 3.2 Patch Level: 33 Release Status: release Description: "fc -e echo" and "fc -e echo -1" should simply run the last command, but the latter runs the last-but-one command. Even worse, "fc -e echo xxx" reports "bash: fc: history specification out of range" when "xxx" is the last command run (provided that there is no other "xxx" in the history. [Detailed description of the problem, suggestion, or complaint.] Repeat-By: Run three commands to get them in the history, say, "aaa, "bbb" and "ccc" (it doesn't matter that they aren't found). Now "fc -e echo -1" will run "bbb" instead of "ccc". Similar, "fc -e echo ccc" will report the history specification out of range error. I have a small shell function that uses fc in this way: please () { fc -e 'sed -i "s/^/sudo /"' -1 } It works fine without the "-1" but that argument was needed for compatability with some other shell (which one is lost in the mists of time) and the bug has been annoying me for some little while so I decided to track it down Fix: The fix is simply to move the delete_last_history() call _after_ the block that calculates histbeg and histend. Patch follows: diff -up bash-3.2/builtins/fc.def.fc bash-3.2/builtins/fc.def --- bash-3.2/builtins/fc.def.fc 2006-07-28 02:44:09.000000000 +0100 +++ bash-3.2/builtins/fc.def 2008-03-13 17:21:15.000000000 +0000 @@ -290,11 +290,6 @@ fc_builtin (list) line was actually added (HISTIGNORE may have caused it to not be), so we check hist_last_line_added. */ - /* "When not listing, he fc command that caused the editing shall not be - entered into the history list." */ - if (listing == 0 && hist_last_line_added) - delete_last_history (); - last_hist = i - 1 - hist_last_line_added; if (list) @@ -322,6 +317,11 @@ fc_builtin (list) histbeg = histend = last_hist; } + /* "When not listing, he fc command that caused the editing shall not be + entered into the history list." */ + if (listing == 0 && hist_last_line_added) + delete_last_history (); + /* We print error messages for line specifications out of range. */ if ((histbeg < 0) || (histend < 0)) {