Sample Header Ad - 728x90

Why is `fc` output different through a pipe in a subshell?

4 votes
0 answers
83 views
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](https://unix.stackexchange.com/questions/794387/multiline-command-substitution-syntax-errors-with-mysterious-1) 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
Asked by Jacktose (533 rep)
May 2, 2025, 10:18 PM
Last activity: May 3, 2025, 09:24 PM