4

I'd like to create an alias to have a quick view of the table format files with comma separator:

alias thead='head | cut -d, -f1- | column -s, -t'

Later using it like this

thead file.csv

However, it doesn't work. What would be the correct syntax?

0

2 Answers 2

10

For anything more advanced than a simple command, use a shell function instead of an alias:

thead () {
    head -- "$1" | cut -d, -f1- | column -s, -t
}

This shell function would run head on its first argument, and then send the result through the pipeline (although, since the cut gets all columns due to -f 1-, this part can probably be removed; I'm leaving it in here as you had it in your original pipeline).

Or,

thead () {
    head -- "$2" | cut -d "$1" -f1- | column -s "$1" -t
}

... to be able to use it as

thead ',' filename

Or even, to allow for an optional delimiter (and use comma if none is given),

thead () {
    local delim=','

    if [ "$#" -gt 1 ]; then
        delim=$1
        shift
    fi
    
    head -- "$1" | cut -d "$delim" -f1- | column -s "$delim" -t
}

The function definition above could be placed wherever you usually define aliases.


The issue with having a pipeline in an alias is that when you use the alias with an argument, this argument would be added to the end of the pipeline, not after the first command in the pipeline.


The bash manual contains the sentence

For almost every purpose, aliases are superseded by shell functions.

3
  • that's good, do you know btw how can I adjust it to accept a separator as a parameter to thead?
    – Max Li
    Feb 21, 2019 at 16:59
  • @MaxLi See updated answer.
    – Kusalananda
    Feb 21, 2019 at 17:01
  • @MaxLi I noticed that the delimiter was also present in the column command and that your cut command is a no-op. I fixed delimiter for column and added a note about the cut.
    – Kusalananda
    Feb 21, 2019 at 18:55
10

alias expansion is just text substitution which is parsed again by the shell, so when you do:

thead file.csv

That's just replaced with:

head | cut -d, -f1- | column -s, -t file.csv

and interpreted again.

If you had written:

<file.csv thead

or

cat file.csv | thead

or

{ thead; } < file.csv

It would have worked as it would have been replaced with:

<file.csv head | cut -d, -f1- | column -s, -t
cat file.csv | head | cut -d, -f1- | column -s, -t
{ head | cut -d, -f1- | column -s, -t; } < file.csv

respectively. In any case, as @Kusalananda says, it's much better to use functions or scripts than aliases for that. Here, I'd just do:

thead() { head "$@" | cut -d, -f1- | column -s, -t; }

So you can do thead -n 12 file.csv file2.csv for instance.

1
  • I think this is the better answer as it clearly explains why the OP’s attempt didn’t work.
    – comfreak
    Feb 21, 2019 at 21:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .