Isso funciona de uma só vez no arquivo e não precisa armazenar todo o arquivo na memória. Mantém descritores de arquivos abertos para cada arquivo de destino.
awk -F '\t' '
NR==FNR {population[$1]=$2; next}
FNR==1 {
for (i=1; i<=NF; i++) {
destination[i] = population[$i] ".txt"
}
}
{
delete separator
for (i=1; i<=NF; i++) {
printf "%s%s", separator[destination[i]], $i > destination[i]
separator[destination[i]] = FS
}
for (file in separator) {
printf "\n" > file
}
}
' populations.txt database.txt