Aliased pipeline using head and cut

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.


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.

Tags:

Bash

Alias