Você pode chamar lsof
para listar os arquivos abertos do processo do shell. Use -a -p $$
para limitar a saída ao processo do shell ( $$
), -d 1
para limitar a saída ao descritor de arquivo 1 (por exemplo) e -F n
para imprimir a saída no formato analisável. Aqui está um snippet de shell que lida com caracteres arbitrários em nomes de arquivos:
output_file=$(lsof -a -p $$ -d 1 -F pn; echo .)
output_file=${output_file%.}
output_file=${output_file#n}
Se o nome do arquivo não contiver uma nova linha, você poderá sair com output_file=$(lsof -a -p $$ -d 1 -F pn | sed -n '2s/.//p')
.
Observe que o nome do arquivo pode nem sempre existir, especialmente se o arquivo foi excluído.
No Linux, outra maneira de acessar os nomes dos arquivos é através de /proc/$$/fd
: /proc/$$/fd/1
é um link simbólico ligeiramente mágico para o arquivo aberto pelo shell no descritor de arquivo 1 (o link funciona mesmo se o nome do arquivo retornado por readlink
não existe, por exemplo, no caso de um arquivo excluído).
Geralmente, é uma péssima ideia usar qualquer informação obtida dessa maneira. Se alguém chamar seu script com a saída redirecionada para um arquivo, ele não vai gostar se você se comportar de maneira diferente por causa da localização do arquivo ou afetar o arquivo de outras maneiras que não sejam anexá-lo a ele. Há uma exceção: você pode querer reagir de forma diferente, dependendo de estar escrevendo para um terminal ou para outra coisa (canal, soquete, arquivo), por exemplo, para exibir cores ou indicadores de progresso em um terminal. Existe um teste específico para determinar se um descritor de arquivo está conectado a um terminal:
if [ -t 2 ]; then
# stderr is a terminal
printf 1>&2 '\e[31mError: widget not found\e[0m'
else
# stderr is not a terminal
echo 1>&2 'Error: widget not found'
fi