Home > Mobile >  What does "-" before an argument to "head" do?
What does "-" before an argument to "head" do?

Time:06-13

I have a simple code here but am having some trouble understanding it.

$ more $1 | head -$2 | tail -1

For the second parameter, I am running a test txt

$ more joe.txt
i am trying
something
else
to
see
if
head
works
the way
it
should
work

When I run the script I get the error:

$ ./sample.sh jad.txt joe.txt
head: invalid option -- 'j'
Try 'head --help' for more information.

It seems to work when I remove the - in front of the $2.

This is a practice question I found online and I doubt they made a mistake with this one. So either I'm missing something here am doing something wrong.

When I run it without the - in front of $2 I get this:

./sample.sh jad.txt joe.txt
it

My questions here are:

  1. Why does it print "it" only when tail -1 is used? To my understanding tail prints the last 10 lines. So what does the -1 do?
  2. Is the - symbol supposed to do something in front of the $2?

CodePudding user response:

- before a parameter usually means that it's a short (one character) option to the program. -- usually means that it's a long (multiple characters) option. This only by convention though. There are lots of exceptions.

So, when running:

./sample.sh jad.txt joe.txt

your line

more $1 | head -$2 | tail -1

becomes:

more jad.txt | head -joe.txt | tail -1

And that makes head complain. You've given it the option -joe.txt which is interpreted as the short option -j but head doesn't have a -j option.

So what does the -1 do?

tail -1 means print the last 1 line(s) from the input.
tail -2 means print the last 2 line(s) from the input.
etc...
head -1 means print the first 1 lines(s) from the input.
head -2 means print the first 2 lines(s) from the input.
etc...

CodePudding user response:

It's not a mistake if you invoke it correctly (assuming this is the output you expect):

./sample.sh joe.txt 5
see
./sample.sh joe.txt 4
to
./sample.sh joe.txt 3
else

what it's a mistake is not checking for valid options in sample.sh

You should do something like

#! /bin/bash

usage() {
    printf 'usage: %s file number\n' "$0" >&2
    exit 1
}

if [[ $# != 2 ]]
then
    usage
fi

re='^[0-9] $'
if ! [[ "$2" =~ $re ]]
then
    printf 'ERROR: not a number: %s\n' "$2" >&2
    usage
fi

more "$1" | head -n $2 | tail -1
  • Related