Encontrando o diretório tmp correto em múltiplas plataformas

40

Eu tenho um script que precisa criar arquivos temporários para seu trabalho e limpar depois de si mesmo. Minha pergunta é sobre encontrar o diretório base correto para os arquivos temporários.

O script precisa funcionar em várias plataformas: Git Bash (Windows), Solaris, Linux, OSX. Em cada plataforma, o diretório temporário preferido é expresso de maneira diferente:

  • Windows: %TMP% (e possivelmente %TEMP% )
  • OSX: $TMPDIR
  • Linux, UNIX: deveria ser $TMPDIR , mas parece não estar configurado em vários sistemas que eu tentei

Então, no meu script, adicionei este clichê:

if test -d "$TMPDIR"; then
    :
elif test -d "$TMP"; then
    TMPDIR=$TMP
elif test -d /var/tmp; then
    TMPDIR=/var/tmp
else
    TMPDIR=/tmp
fi

Isso parece muito tedioso. Existe uma maneira melhor?

    
por janos 18.12.2014 / 10:18

3 respostas

59

Uma maneira um pouco mais portátil de manipular arquivos temporários é usar mktemp . Ele criará arquivos temporários e retornará seus caminhos para você. Por exemplo:

$ mktemp
/tmp/tmp.zVNygt4o7P
$ ls /tmp/tmp.zVNygt4o7P
/tmp/tmp.zVNygt4o7P

Você pode usá-lo em um script com bastante facilidade:

tmpfile=$(mktemp)
echo "Some temp. data..." > $tmpfile
rm $tmpfile

Lendo a página do manual, você deve ser capaz de definir opções de acordo com suas necessidades. Por exemplo:

  • -d cria um diretório em vez de um arquivo.
  • -u gera um nome, mas não cria nada.

Usando -u você pode recuperar o diretório temporário facilmente com ...

$ tmpdir=$(dirname $(mktemp -u))

Mais informações sobre mktemp estão disponíveis aqui .

Editar em relação ao Mac OS X: Eu nunca usei um sistema Mac OSX, mas de acordo com um comentário de Tyilo abaixo, isso parece que o mktemp do Mac OSX requer que você forneça um modelo (que é um argumento opcional no Linux). Citando:

The template may be any file name with some number of "Xs" appended to it, for example /tmp/temp.XXXX. The trailing "Xs" are replaced with the current process number and/or a unique letter combination. The number of unique file names mktemp can return depends on the number of "Xs" provided; six "Xs" will result in mktemp selecting 1 of 56800235584 (62 ** 6) possible file names.

A página man também diz que esta implementação é inspirada na página man do OpenBSD para mktemp . Uma divergência semelhante pode, portanto, ser observada pelos usuários do OpenBSD e do FreeBSD também (veja a seção Histórico ).

Agora, como você provavelmente percebeu, isso exige que você especifique um caminho de arquivo completo, incluindo o diretório temporário que está procurando em sua pergunta. Esse pequeno problema pode ser tratado usando a opção -t . Embora essa opção pareça exigir um argumento ( prefix ), parece que mktemp depende de $TMPDIR quando necessário.

Em resumo, você deve conseguir o mesmo resultado acima usando ...

$ tmpdir=$(dirname $(mktemp tmp.XXXXXXXXXX -ut))

Qualquer feedback dos usuários do Mac OS X seria muito apreciado, já que eu não posso testar essa solução sozinho.

    
por 18.12.2014 / 10:34
9

Se você está procurando a mesma coisa em menos linhas ...

for TMPDIR in "$TMPDIR" "$TMP" /var/tmp /tmp
do
    test -d "$TMPDIR" && break
done

Você pode escrever isso em um.

    
por 18.12.2014 / 10:38
6

Você pode fazer:

: "${TMPDIR:=${TMP:-$(CDPATH=/var:/; cd -P tmp)}}"
cd -- "${TMPDIR:?NO TEMP DIRECTORY FOUND!}" || exit

O shell deve encontrar um diretório executável em uma das quatro alternativas ou sair com um erro significativo. Ainda assim, o POSIX define a variável $TMPDIR (para sistemas XCU) :

TMPDIR This variable shall represent a pathname of a directory made available for programs that need a place to create temporary files.

Também requer o caminho /tmp .

    
por 18.12.2014 / 13:26