4

Why does echo "$(fc -l -1)" show the previous command, but echo "$(fc -l -1 | cat)" show the current command?

$ testfc () { > echo "$(fc -l -1)" > echo "$(fc -l -1 | cat)" > } $ echo foo foo $ testfc 1820 echo foo 1821 testfc 

More detail

I was testing things for a rabbit-hole question and ended up down another rabbit hole. I created this function to try different ways of accessing the previous or current command history number with the fc and history built-ins:

testfc () { printf 'fc1\t'; fc -l -1 printf 'fc1|\t'; fc -l -1 | cat printf '(fc1)\t%s\n' "$(fc -l -1)" printf '(fc1|)\t%s\n' "$(fc -l -1 | cat)" # this one is weird printf 'fc0\t'; fc -l -0 printf 'fc0|\t'; fc -l -0 | cat printf '(fc0)\t%s\n' "$(fc -l -0)" printf '(fc0|)\t%s\n' "$(fc -l -0 | cat)" printf 'hist\t'; history 1 printf 'hist|\t'; history 1 | cat printf '(hist)\t%s\n' "$(history 1)" printf '(hist|)\t%s\n' "$(history 1 | cat)" str='\!' printf '@P\t%s\n' "${str@P}" printf 'HC\t%s\n' "$HISTCMD" } 

Generally, fc -l -0 & history 1 show the current command, and fc -l -1 shows the previous command. Their outputs don't change when run in a $() subshell or piped through cat. Except "$(fc -l -1 | cat)"!

1831 $ echo foo foo 1832 $ testfc fc1 1831 echo foo fc1| 1831 echo foo (fc1) 1831 echo foo (fc1|) 1832 testfc # <-- WHAT? fc0 1832 testfc fc0| 1832 testfc (fc0) 1832 testfc (fc0|) 1832 testfc hist 1832 2025-05-02 15:10:59 testfc hist| 1832 2025-05-02 15:10:59 testfc (hist) 1832 2025-05-02 15:10:59 testfc (hist|) 1832 2025-05-02 15:10:59 testfc @P 1832 HC 1832 1833 $ fc -l -2 1831 echo foo 1832 testfc 

Context

$ echo $BASH_VERSION 5.2.37(1)-release $ type fc fc is a shell builtin $ type history history is a shell builtin $ type cat cat is /usr/bin/cat 
2
  • 2
    Because fc in a subshell writes its own history into $HISTFILE, with a 4K buffer. That's the history that (fc) searches. Outside a subshell, fc accesses the normal $HISTORY. Commented May 3 at 21:50
  • Then why does | cat change its output? Commented May 4 at 18:20

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.