Extracting Lines Common For All Files
The following recursive command extracts lines common for all files. An advantage is that we don't have to sort anything.
intersect() { f="$1"; if shift; then grep -Fxf "$f" | intersect "$@"; else cat; fi; }
common() { f="$1"; shift; intersect "$@" < "$f"; }
common *
The trick here is to intersect files recursively. If we understand files as mathematical sets of lines the question boils down to »Given sets a, b, …, n, how to compute a ∩ b ∩ … ∩ n«.
We can compute the intersection a ∩ b with the command grep -Fxf a b
which is the same as cat b | grep -Fxf a
or cat a | grep -Fxf b
(useless use of cat only for better readability). The order of a and b does not matter.
To compute the intersection a ∩ b ∩ c we can compute (a ∩ b) ∩ c. How to compute (a ∩ b) is already known (see above), so we apply the same approach to the result of (a ∩ b): cat a | grep -Fxf b | grep -Fxf c
. Alternatively, you can replace the entire grep
command by common a b
from moreutils
.
How to proceed from there should be clear.
Use 2nd Column Instead Of Whole Lines
To use only the 2nd column instead of whole lines we can either work on modified copies
for f in *; do
awk '{ print $2 }' "$f" > "$f-col2"
done
common *-col2
… or adapt the function
mask() { awk '{ print $2 }' "$@"; }
intersect() { f="$1"; if shift; then grep -Fxf <(mask "$f") | intersect "$@"; else cat; fi; }
common() { f="$1"; shift; mask "$f" | intersect "$@"; }
common *