Correção ou alternativa para mktemp no OS X

73

Estou olhando para um script bash que alguém escreveu que usa mktemp:

TEMP=`mktemp --directory`

No entanto, esta linha não funciona na minha máquina (OS X 10.6).

Como eu consertaria essa linha para que ela seja compatível com uma plataforma cruzada * x-like? EDIT: Um comando alternativo seria suficiente também.

mente.
fonte

Respostas:

109

A seguir, o que acabei usando para criar de maneira confiável um diretório temporário que funcione no Linux e no Darwin (todas as versões anteriores ao Mac OS X 10.11), sem codificação $TMPDIRou /tmp:

mytmpdir=`mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir'`

Fundo:

O comando GNU mktemp não requer argumentos. O Plain mktempfuncionará e cria um arquivo temporário no diretório temporário do sistema.

O Plain mktemp -dcriará um diretório em vez de um arquivo, que é o que você deseja usar no Linux.

(gnu-coreutils)$ man mktemp
> ..
> If DIR is not specified, uses $TMPDIR if set, else /tmp.
> ..

Por padrão, o GNU mktemp usa o modelo tmp.XXXXXXXXXXpara o nome do subdiretório (ou arquivo). Para personalizar este modelo, a -topção pode ser usada.

O mktemp do OSX não possui modelo padrão e requer que um modelo seja especificado. Infelizmente, onde o GNU mktemp usa o modelo como -topção, no OSX isso é passado como argumento posicional. Em vez disso, o mktemp do OSX tem uma -topção que significa outra coisa. A -topção no OSX está documentada como um "prefixo" para o modelo. Ele é expandido para {prefix}.XXXXXXXX, portanto, adiciona os Xs automaticamente (por exemplo, mktemp -d -t examplepode ser criado example.zEJZWCTQno diretório temp).

Fiquei surpreso ao descobrir que, em muitos ambientes Linux, não$TMPDIR está definido por padrão. Muitos programas CLI suportam quando definidos, mas ainda precisam de um padrão . Isso significa que a passagem para mktemp ou mkdir é perigosa, pois pode produzir no diretório raiz do disco local (devido ao fato de $ TMPDIR estar desconfigurado e se tornar uma cadeia vazia)./tmp$TMPDIR/example.XXXXXXXX/example.XXXXXXXX

No OSX, $TMPDIRsempre está definido e (pelo menos no shell padrão) não está definido como /tmp(que é um link simbólico para /private/tmp), mas como /var/folders/dx/*****_*************/T. Portanto, o que fazemos para o OSX, deve respeitar esse comportamento padrão.

Concluindo, a seguir, o que acabei usando para criar de maneira confiável um diretório temporário que funcione no Linux e no Darwin (Mac OS X), sem codificar permanentemente $TMPDIRou /tmp:

mytmpdir=`mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir'`

A primeira parte é para Linux. Este comando falhará no Darwin (Mac OS X) com o código de status do erro 1respondendo com "use: ...". É por isso que ignoramos o stderr e, em vez disso, executamos a variante do Mac. O mytmpdirprefixo é usado apenas no Mac (onde é necessário definir essa opção).

Timo Tijhof
fonte
12
Realmente legal. Às vezes, o comportamento diferente do OS X é irritante.
Therealmarv
6
@therealmarv Prefiro dizer sempre.
Nikita Volkov #
10
Acabei de mktemp -drodar no OS X 10.11.5 El Capitan e funcionou como esperado file $(mktemp -d):: /var/folders/j4/htlnmbf97vlcdszj7_x8g0vh4k3_fp/T/tmp.JXmsrQnL: directory
Heath Borders
2
Sim. Fiquei surpreso como você era que isso Just Worked ™.
21306 Heath Borders
11
Além disso, se você executar mktemp -d -t 'mytmpdir'no Linux (testado com mktempfrom coreutils 8.26), ele funcionará conforme o esperado.
15

Você precisa fornecer um modelo. mktemp -d /tmp/foo.XXXXDeveria trabalhar. Eu nunca vi --directory. O --sugere que é uma extensão GNU.

Kyle Jones
fonte
6
Se você deseja usar $TMPDIRquando disponível, faça mktemp -d "${TMPDIR:-/tmp}"/foo.XXXX. Isso funciona no bash no Mac e no Debian, por isso parece portátil.
Tom Anderson
9

Mude --directorypara -d. O primeiro é um GNU-ism, mas o GNU mktempdo coreutils também suporta -d. O mktempOS X é o mesmo do BSD, portanto -ddeve ser bastante portátil entre os sistemas que realmente fornecem um mktempprograma.

James Sneeringer
fonte
Eu apenas tentei mktemp -de também não funciona.
mente.
11
Kyle tem a resposta completa. O mktempOS X requer um modelo. O script que você está usando assume as convenções GNU, que usam um modelo padrão se nenhum for fornecido.
James Sneeringer 26/01
O problema é que o unix espera XXXXXser fornecido no modelo em que o OS X não tem certeza se existe um sinalizador de modelo compatível?
user3467349
2
mktempno OS X 10.11.5 El Capitan funciona para mim file $(mktemp -d)::/var/folders/j4/htlnmbf97vlcdszj7_x8g0vh4k3_fp/T/tmp.JXmsrQnL: directory
Heath Borders
4
temp_dir="$(mktemp -q -d -t "$(basename "$0").XXXXXX")"
  • mktemppara BSD (incluindo OSX ) requer um modelo, mas permite qualquer número de Xs no modelo.
  • (GNU) mktemppara Linux não requer um modelo, no entanto, se um modelo for especificado, o número de Xs deverá ser 6.

Observe que -testá obsoleto para o GNUmktemp , portanto, um código mais à prova de futuro seria

temp_dir="$(mktemp -q -d -t "$(basename "$0").XXXXXX" 2>/dev/null || mktemp -q -d)"
go2null
fonte