Getting head to display all but the last line of a file: command substitution and standard I/O redirection

gkb0986 picture gkb0986 · Aug 8, 2013 · Viewed 27.4k times · Source

I have been trying to get the head utility to display all but the last line of standard input. The actual code that I needed is something along the lines of cat myfile.txt | head -n $(($(wc -l)-1)). But that didn't work. I'm doing this on Darwin/OS X which doesn't have the nice semantics of head -n -1 that would have gotten me similar output.

None of these variations work either.

cat myfile.txt | head -n $(wc -l | sed -E -e 's/\s//g')
echo "hello" | head -n $(wc -l | sed -E -e 's/\s//g')

I tested out more variations and in particular found this to work:

cat <<EOF | echo $(($(wc -l)-1))
>Hola
>Raul
>Como Esta
>Bueno?
>EOF
3

Here's something simpler that also works.

echo "hello world" | echo $(($(wc -w)+10))

This one understandably gives me an illegal line count error. But it at least tells me that the head program is not consuming the standard input before passing stuff on to the subshell/command substitution, a remote possibility, but one that I wanted to rule out anyway.

echo "hello" | head -n $(cat && echo 1)

What explains the behavior of head and wc and their interaction through subshells here? Thanks for your help.

Answer

dunc123 picture dunc123 · Aug 8, 2013

head -n -1 will give you all except the last line of its input.