Linux / Comando join: combinar arquivos por uma chave comum
join combina linhas de dois arquivos de texto quando os valores de um campo-chave são iguais. Por padrão, usa o primeiro campo, exige entradas ordenadas por essa chave e mostra apenas os pares correspondentes. Diferentemente de paste, que combina pela posição das linhas, join compara o conteúdo da chave.
Uma chave é o valor usado para identificar a correspondência, como um código de cliente. Ela não precisa ser única: se houver repetições nos dois arquivos, um mesmo valor pode produzir várias combinações. Para conferir registros sem par, use -a ou -v conforme o resultado desejado.
Sintaxe, campos e critérios de ordenação
join [opção...] arquivo1 arquivo2
Substitua os marcadores pelos nomes reais. As opções deste guia seguem o GNU Coreutils; consulte join --version, join --help ou man join para a implementação instalada. O argumento - pode representar a entrada padrão em um dos dois arquivos, mas não em ambos.
Sem -t, espaços e tabulações delimitam campos, e os brancos iniciais são ignorados. As posições começam em 1. Na saída padrão, aparecem a chave, os demais campos do primeiro arquivo e os demais campos do segundo. Com -t ':', cada dois-pontos é um separador significativo tanto na leitura quanto na saída.
A ordenação deve usar a chave, o separador e a localidade compatíveis com join. A localidade, ou locale, define regras como a comparação de texto. Nos dados simples abaixo, LC_ALL=C é aplicado tanto a sort quanto a join para usar a mesma comparação. As chaves são strings, isto é, sequências de caracteres; ordenação numérica com sort -n não substitui automaticamente a ordem textual exigida.
Preparar, ordenar e combinar os dados
Execute o bloco inteiro em um terminal Bash, dentro de uma pasta onde possa criar um diretório. Ele prepara doze arquivos de prática, incluindo as cópias ordenadas e os dados para os exemplos seguintes, em uma pasta exclusiva. Os parênteses criam um subshell: ao terminar, a sessão volta ao diretório anterior. set -eu interrompe este bloco simples após falhas e uso de variáveis não definidas.
(
set -eu
labdir=$(mktemp -d ./join-demo.XXXXXX)
cd "$labdir"
printf 'b Bob\na Ana\nc Cat\n' > names.txt
printf 'a 7\nb 12\n' > scores.txt
LC_ALL=C sort -k1,1 names.txt > names.sorted
LC_ALL=C sort -k1,1 scores.txt > scores.sorted
LC_ALL=C join --check-order names.sorted scores.sorted
LC_ALL=C join --check-order -a 1 names.sorted scores.sorted
printf 'a:Ana\nb:Bob\n' > users.txt
printf 'a:reader\nb:writer\n' > roles.txt
LC_ALL=C sort -t ':' -k1,1 users.txt > users.sorted
LC_ALL=C sort -t ':' -k1,1 roles.txt > roles.sorted
LC_ALL=C join --check-order -t ':' users.sorted roles.sorted
printf 'Ana a\nBob b\nCat c\n' > names-key2.txt
printf 'a 7\nb 12\nd 99\n' > scores-extra.txt
printf 'a Ana\na Alice\n' > names-duplicate.txt
printf 'a 7\na 8\n' > scores-duplicate.txt
printf 'Arquivos do laboratório: %s\n' "$PWD"
)
A primeira combinação mostra a Ana 7 e b Bob 12. Na execução com -a 1, essas duas linhas aparecem novamente, seguidas de c Cat, sem pontuação. O exemplo com dois-pontos mostra a:Ana:reader e b:Bob:writer. A última linha informa o caminho completo dos arquivos.
Esses resultados foram conferidos com GNU join e sort 8.32 no Bash do Git para Windows. O exemplo cria somente dados fictícios e preserva as entradas ao produzir cópias ordenadas. Para os comandos seguintes, entre no caminho impresso usando cd com o caminho entre aspas. Os arquivos permanecem disponíveis após o subshell terminar.
Verificar chaves sem correspondência
Com os dados originais, LC_ALL=C join --check-order -v 1 names.sorted scores.sorted mostra apenas c Cat. Já -a 1 inclui os pares e as linhas sem par do primeiro arquivo. Os números 1 e 2 indicam os arquivos na ordem em que foram passados ao comando, não números de campos.
O arquivo scores-extra.txt também contém d 99, sem nome correspondente. Execute LC_ALL=C join --check-order -a 1 -a 2 -e SEM_DADO -o '0,1.2,2.2' names.sorted scores-extra.txt. A saída tem a Ana 7, b Bob 12, c Cat SEM_DADO e d SEM_DADO 99, uma por linha.
Nesse formato, 0 representa a chave da linha de saída, 1.2 o segundo campo do primeiro arquivo e 2.2 o segundo campo do segundo arquivo. -e preenche campos de saída ausentes, e -o define a estrutura que deve aparecer mesmo quando falta um par. Para mostrar somente os registros ausentes dos dois lados, use LC_ALL=C join --check-order -v 1 -v 2 names.sorted scores-extra.txt: o resultado é c Cat e d 99.
Escolher outra chave e a ordem de saída
Em names-key2.txt, cada nome vem antes do código: Ana a, Bob b e Cat c. A chave está no campo 2 e já está na ordem a, b, c. Para combiná-la com o campo 1 das pontuações, execute LC_ALL=C join --check-order -1 2 -2 1 names-key2.txt scores.sorted. O resultado continua sendo a Ana 7 e b Bob 12.
Se você receber esse arquivo em outra ordem, produza antes uma cópia com LC_ALL=C sort -k2,2 names-key2.txt > names-key2.sorted e use essa cópia na combinação. Não reutilize uma ordenação pelo campo 1 quando a chave escolhida passou ao campo 2.
Para mostrar apenas nome e pontuação dos dados iniciais, LC_ALL=C join --check-order -o '1.2,2.2' names.sorted scores.sorted retorna Ana 7 e Bob 12. Aqui a chave foi omitida da saída por escolha explícita; ela continua sendo usada para localizar os pares.
Conferir duplicações e erros de ordem
Os arquivos names-duplicate.txt e scores-duplicate.txt têm duas linhas com chave a em cada lado. LC_ALL=C join --check-order names-duplicate.txt scores-duplicate.txt produz quatro linhas: a Ana 7, a Ana 8, a Alice 7 e a Alice 8. São duas vezes duas combinações, não apenas duas linhas nem a escolha automática do primeiro par.
Confirme se essas repetições fazem sentido para os dados antes de usar a saída. Se o objetivo exige uma chave única, investigue as duplicações na origem; remover linhas apenas para reduzir a contagem pode eliminar informações legítimas.
O names.txt inicial está fora de ordem. LC_ALL=C join --check-order names.txt scores.sorted falha; na verificação com essa entrada, nenhuma linha foi escrita. Quando a desordem aparece mais adiante, porém, o programa pode já ter emitido parte da saída antes de detectá-la. Uma mensagem de erro e um status diferente de zero invalidam esse resultado como combinação completa. Refaça a ordenação em uma cópia com o critério correto e execute novamente; não use --nocheck-order para tentar corrigir dados desordenados.
Para conferir uma falha no terminal, execute o comando e consulte echo "$?" imediatamente depois, sem outro comando intermediário. A presença de algumas linhas na tela não prova sucesso. Nos exemplos, --check-order é solicitado explicitamente para verificar a ordem mesmo quando a situação não acionaria um diagnóstico padrão.
Opções principais
| Opção | Uso |
|---|---|
-t caractere |
Define o separador dos campos de entrada e saída. |
-1 N / -2 N |
Escolhe o campo-chave de cada arquivo, contado a partir de 1. |
-a 1 / -a 2 |
Acrescenta registros sem par do arquivo indicado aos pares normais. |
-v 1 / -v 2 |
Mostra apenas registros sem par do arquivo indicado. |
-o formato |
Escolhe os campos e sua ordem; 0 representa a chave. |
-e texto |
Preenche campos ausentes solicitados na saída. |
--check-order |
Exige a verificação da ordem das entradas; descarte resultados de execuções que falhem. |
Salvar sem sobrescrever as entradas
Use (set -C; LC_ALL=C join --check-order names.sorted scores.sorted > joined.txt) para criar uma saída nova. Após sucesso, confira com cat joined.txt. O ajuste fica no comando entre parênteses e impede sobrescrever esse arquivo regular se ele já existir. Caso a combinação falhe, o arquivo criado pode conter saída parcial: não o trate como resultado válido.
Não use como destino um dos arquivos de entrada: o redirecionamento do shell pode esvaziá-lo antes de join ler os dados. Confira o término bem-sucedido, as chaves ausentes, as duplicações e os campos resultantes antes de substituir arquivos importantes.
Pergunta frequente
Posso combinar arquivos sem ordená-los antes?
Para este procedimento, prepare os dois arquivos na ordem da chave, com separador e localidade compatíveis. Use cópias ordenadas e --check-order para validar. Não conclua que a entrada está correta apenas porque um comando sem verificação explícita retornou algumas linhas.
Documentação oficial
Consulte as opções gerais do GNU join, as regras de ordenação para join e a página de manual publicada pelo Ubuntu para Coreutils 8.32.




