Localizando o diretório tmp correto em várias plataformas

46

Eu tenho um script que precisa criar arquivos temporários para o seu trabalho e limpar depois de si mesmo. Minha pergunta é sobre como 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 estar, $TMPDIRmas parece não estar configurado em vários sistemas que tentei

Então, no meu script, adicionei este boilerplate:

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 entediante. Existe uma maneira melhor?

Pare o dano contínuo a Monica
fonte
6
Basta usar ${TMPDIR-/tmp}no Unix-likes. TMPDIRexiste (pelo sistema ou administrador ou usuário) para informar quando não usar /tmpem arquivos temporários.
Stéphane Chazelas

Respostas:

72

Uma maneira um pouco mais portátil de lidar com 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 facilmente:

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

Lendo a página de manual, você poderá 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 -uvocê pode recuperar o diretório temporário facilmente com ...

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

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

Editar sobre o Mac OS X: Eu nunca usei um sistema Mac OSX, mas de acordo com um comentário de Tyilo abaixo, parece que o Mac OSX mktempexige que você forneça um modelo (que é um argumento opcional no Linux). Citação:

O modelo pode ser qualquer nome de arquivo com algum número de "Xs" anexado a ele, por exemplo /tmp/temp.XXXX. Os "Xs" à direita são substituídos pelo número do processo atual e / ou uma combinação de letras exclusiva. O número de nomes de arquivos exclusivos que o mktemp pode retornar depende do número de "Xs" fornecidos; seis "Xs" resultarão no mktemp selecionando 1 de 56800235584 (62 ** 6) nomes de arquivos possíveis.

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

Agora, como você provavelmente notou, isso exige que você especifique um caminho completo do arquivo, incluindo o diretório temporário que você está procurando na sua pergunta. Este pequeno problema pode ser tratado com o -tinterruptor. Embora essa opção pareça exigir um argumento ( prefix), parece que se mktempbaseia $TMPDIRquando necessário.

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

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

Qualquer feedback dos usuários do Mac OS X será muito apreciado, pois não consigo testar esta solução.

John WH Smith
fonte
O OP abordou esse problema em um comentário excluído; Receio não poder fornecer uma resposta para sistemas que exigem gitbashuma interface shell, portanto, meu "ligeiramente". Eu realmente seria incapaz de dizer onde os arquivos temporários são armazenados em um sistema Windows ...
John WH Smith
1
idem isso. Alguns loucos c:\User\Name\..............\stuff. E provavelmente existem 100 deles. Ainda assim, algumas distribuições linux estão chegando ao mesmo nível de loucura /var. Eu só estava curioso. Pareceu-me uma maneira estranha de dizer tudo - na minha experiência, a frustração é muito portátil e a conveniência, menos. Muito boa resposta de qualquer maneira.
mikeserv
1
Há um ano, escrevi um script Bash para manipular arquivos do Windows Restore Point que funcionam no Win2K até o WinXP (versões posteriores tratam essas coisas de maneira diferente). Meu script usa WINDOWS/Tempou Windows/Tempcomo o diretório padrão para seus arquivos temporários; esse diretório também existe nas máquinas com Windows 7. Mas meu script permite que o usuário forneça um diretório temporário alternativo na linha de comando.
PM 2Ring
Isso não funcionaria no OS X, pois você precisa fornecer um modelo para mktemp.
Tyilo
1
Desde El Capitan, mktempsimplesmente funciona: simple mktempretorna um arquivo e mktemp -dretorna um diretório; nenhum modelo é necessário. O manual não é atualizado.
Franklin Yu
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ê poderia escrever isso em um.

frostschutz
fonte
Você provavelmente também deve testar se é gravável.
Frostschutz
@janos: E se tudo mais falhar, peça ao usuário que forneça um caminho para os arquivos temporários ou permita que eles especifiquem um na linha de comando.
PM 2Ring
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 4 alternativas ou sair com um erro significativo. Ainda assim, o POSIX define a $TMPDIRvariável (para sistemas XCU) :

TMPDIR Essa variável deve representar o nome do caminho de um diretório disponibilizado para programas que precisam de um local para criar arquivos temporários.

Também requer o /tmpcaminho.

mikeserv
fonte
1
Esta é a única resposta correta aqui IMO. Não sei o que está fazendo sentado no fundo sem votos ...
Graeme
2
@ Graeme: talvez porque seja totalmente ilegível?
ssc
Fiz um voto positivo, mas depois o retirei - sim, esta resposta é uma bagunça. Parece estar em uma trilha útil, mas não está claro o que o snippit de código está tentando fazer-- a primeira linha é um comentário e a segunda um é um erro (no bash, de qualquer maneira). Poderia usar algum trabalho.
Don escotilha
Ah, entendo, a primeira versão da resposta foi mais clara (ainda é um erro na 2ª linha, se você realmente tentar executá-la) ... e, em seguida, uma série de edições destruiu completamente o exemplo de código, tornando-o um absurdo. Poderia usar outra passagem ou dois :-)
Don escotilha