A maioria dos comandos possui um único canal de entrada (entrada padrão, descritor de arquivo 0) e um único canal de saída (saída padrão, descritor de arquivo 1) ou então opera em vários arquivos que eles abrem sozinhos (para você passar um nome de arquivo). (Isso é um acréscimo ao erro padrão (fd 2), que normalmente filtra todo o caminho até o usuário.) No entanto, às vezes é conveniente ter um comando que atue como um filtro de várias fontes ou de vários destinos. Por exemplo, aqui está um script simples que separa as linhas com números ímpares em um arquivo das linhas pares
while IFS= read -r line; do
printf '%s\n' "$line"
if IFS= read -r line; then printf '%s\n' "$line" >&3; fi
done >odd.txt 3>even.txt
Agora, suponha que você queira aplicar um filtro diferente às linhas com números ímpares e às linhas com números pares (mas não reuni-las novamente, isso seria um problema diferente, não possível do shell em geral). No shell, você pode canalizar apenas a saída padrão de um comando para outro comando; Para canalizar outro descritor de arquivo, você precisa redirecioná-lo para o fd 1 primeiro.
{ while … done | odd-filter >filtered-odd.txt; } 3>&1 | even-filter >filtered-even.txt
Outro caso de uso mais simples é filtrar a saída de erro de um comando .
exec M>&N
redireciona um descritor de arquivo para outro pelo restante do script (ou até outro comando alterar os descritores de arquivo novamente). Há alguma sobreposição na funcionalidade entre exec M>&N
e somecommand M>&N
. O exec
formulário é mais poderoso, pois não precisa ser aninhado:
exec 8<&0 9>&1
exec >output12
command1
exec <input23
command2
exec >&9
command3
exec <&8
Outros exemplos que podem ser de interesse:
E para ainda mais exemplos:
PS Essa é uma pergunta surpreendente vinda do autor da publicação mais votada no site que usa o redirecionamento através do fd 3 !
while IFS= read -r line;
? A meu ver, o IFS não tem efeito aqui, pois você atribui valor a apenas uma variável ( linha ). Veja esta pergunta.IFS
faz a diferença, mesmo que você esteja lendo uma variável única (é para manter o espaço em branco principal).sed -ne 'w odd.txt' -e 'n;w even.txt'
?Aqui está um exemplo do uso de FDs extras como controle de chattiness de script bash:
fonte
No contexto de pipes nomeados (fifos), o uso de um descritor de arquivo adicional pode ativar o comportamento de tubulação sem bloqueio.
Consulte: Pipe nomeado fechando prematuramente no script?
fonte
Um descritor de arquivo extra é bom para quando você deseja capturar o stdout em uma variável e ainda assim deseja gravar na tela, por exemplo, em uma interface com o usuário do script bash
fonte
Aqui está outro cenário quando o uso de um descritor de arquivo adicional parece apropriado (no Bash):
Segurança da senha do script do shell dos parâmetros da linha de comando
fonte
Exemplo: usando flock para forçar scripts a serem executados em série com bloqueios de arquivo
Um exemplo é usar o bloqueio de arquivos para forçar os scripts a serem executados em série no sistema. Isso é útil se você não quiser que dois scripts do mesmo tipo funcionem nos mesmos arquivos. Caso contrário, os dois scripts interfeririam entre si e possivelmente danificariam os dados.
Use o rebanho funcionalmente definindo bloqueio e desbloqueio
Você também pode agrupar essa lógica de bloqueio / desbloqueio em funções reutilizáveis. O seguinte
trap
shell incorporado liberará automaticamente o bloqueio de arquivo quando o script sair (erro ou êxito).trap
ajuda a limpar os bloqueios de arquivos. O caminho/tmp/file.lock
deve ser um caminho codificado para que vários scripts possam tentar travá-lo.A
unlock
lógica acima é excluir o arquivo antes do bloqueio ser liberado. Dessa forma, ele limpa o arquivo de bloqueio. Como o arquivo foi excluído, outra instância deste programa pode obter o bloqueio do arquivo.Uso de funções de bloqueio e desbloqueio em scripts
Você pode usá-lo em seus scripts como no exemplo a seguir.
Se você deseja que seu código aguarde até que seja capaz de bloquear, você pode ajustar o script como:
fonte
Como exemplo concreto, acabei de escrever um script que precisa das informações de tempo de um subcomando. O uso de um descritor de arquivo extra me permitiu capturar o
time
stderr do comando sem interromper o stdout ou o stderr do subcomando.O que isso faz é apontar
ls
o stderr para fd 3, apontar fd 3 para o stderr do script e apontartime
o stderr para um arquivo. Quando o script é executado, seu stdout e stderr são os mesmos do subcomando, que podem ser redirecionados normalmente. Somentetime
a saída é redirecionada para o arquivo.fonte