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.