Da página lsof
man
Lsof returns a one (1) if any error was detected, including the failure to locate command names, file names, Internet addresses or files, login names, NFS files, PIDs, PGIDs, or UIDs it was asked to list. If the -V option is specified, lsof will indicate the search items it failed to list.
Isso sugere que sua cláusula lsof failed for some other reason
nunca será executada.
Já tentou mover o arquivo enquanto o processo externo ainda o mantém aberto? Se o diretório de destino estiver no mesmo sistema de arquivos, não deverá haver problemas em fazer isso, a menos que você precise acessá-lo sob o caminho original de um terceiro processo, pois o inode subjacente permanecerá o mesmo. Caso contrário, acho que mv
falhará de qualquer maneira.
Se você realmente precisar esperar até que o processo externo termine com o arquivo, é melhor usar um comando que bloqueia em vez de pesquisar repetidamente. No Linux, você pode usar inotifywait
para isso. Por exemplo:
inotifywait -e close_write /path/to/file
Se você precisar usar lsof
(talvez para portabilidade), pode tentar algo como:
until err_str=$(lsof /path/to/file 2>&1 >/dev/null); do
if [ -n "$err_str" ]; then
# lsof printed an error string, file may or may not be open
echo "lsof: $err_str" >&2
# tricky to decide what to do here, you may want to retry a number of times,
# but for this example just break
break
fi
# lsof returned 1 but didn't print an error string, assume the file is open
sleep 1
done
if [ -z "$err_str" ]; then
# file has been closed, move it
mv /path/to/file /destination/path
fi
Atualizar
Conforme observado por @ JohnWHSmith abaixo, o design mais seguro sempre usaria um loop lsof
como acima, pois é possível que mais de um processo tenha o arquivo aberto para gravação (um exemplo pode ser um daemon de indexação mal escrito que abre arquivos com o sinalizador de leitura / gravação quando realmente deveria ser lido somente). inotifywait
ainda pode ser usado em vez de dormir, basta substituir a linha de suspensão por inotifywait -e close /path/to/file
.