Eu faria um uso mais pesado de redirecionamento de E / S :
#!/bin/bash
[[ $1 ]] && [[ ! -f $1 ]] && echo "file $1 dne" && exit 1
[[ $1 ]] && exec 3<$1 || exec 3<&0
[[ $2 ]] && exec 4>$2 || exec 4>&1
fgrep -v "stuff" <&3 >&4
Explicação
-
[[ $1 ]] && [[ ! -f $1 ]] && echo "file $1 dne" && exit 1
Teste se um arquivo de entrada foi especificado como um argumento de linha de comando e se o arquivo existe.
-
[[ $1 ]] && exec 3<$1 || exec 3<&0
Se
$1
estiver definido, ou seja, um arquivo de entrada tiver sido especificado, o arquivo especificado será aberto no descritor de arquivo3
, caso contrário,stdin
será duplicado no descritor de arquivo3
. -
[[ $2 ]] && exec 4>$2 || exec 4>&1
Da mesma forma, se o
$2
estiver definido, ou seja, um arquivo de saída tiver sido especificado, o arquivo especificado será aberto no descritor de arquivo4
, caso contrário,stdout
será duplicado no descritor de arquivo4
. -
fgrep -v "stuff" <&3 >&4
Por fim,
fgrep
é invocado, redirecionando seusstdin
estdout
para os descritores de arquivos previamente definidos3
e4
, respectivamente.
Reabertura de entrada e saída padrão
Se você preferir não abrir descritores de arquivos intermediários, uma alternativa é substituir os descritores de arquivo correspondentes a stdin
e stdout
diretamente aos arquivos de entrada e saída especificados:
#!/bin/bash
[[ $1 ]] && [[ ! -f $1 ]] && echo "file $1 dne" && exit 1
[[ $1 ]] && exec 0<$1
[[ $2 ]] && exec 1>$2
fgrep -v "stuff"
Uma desvantagem dessa abordagem é que você perde a capacidade de diferenciar a saída do próprio script da saída do comando que é o destino do redirecionamento. Na abordagem original, você pode direcionar a saída do script para os stdin
e stdout
não modificados, que, por sua vez, podem ter sido redirecionados pelo responsável pela chamada do script. Os arquivos de entrada e saída especificados ainda podem ser acessados por meio dos descritores de arquivos correspondentes, que são distintos do script stdin
e stdout
.