Correção ou alternativa para mktemp no OS X

58

Estou vendo um script bash escrito por outra pessoa 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 fosse compatível com plataformas incompatíveis com x * x? EDITAR: Um comando alternativo também seria suficiente.

    
por mindeavor. 26.01.2012 / 20:03

4 respostas

91

A seguir, o que acabei usando para criar de forma confiável um diretório temporário que funciona no Linux e no Darwin (todas as versões anteriores ao Mac OS X 10.11), sem codificar $TMPDIR ou /tmp :

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

Antecedentes:

O comando GNU mktemp não requer argumentos. O mktemp simples funcionará e criará um arquivo temporário no diretório temporário do sistema.

O mktemp -d simples criará um diretório em vez de um arquivo, que é o que você gostaria de 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 template tmp.XXXXXXXXXX para o nome do subdiretório (ou arquivo). Para personalizar este modelo, a opção -t pode ser usada.

O mktemp do OSX não possui um modelo padrão e requer que um modelo seja especificado. Infelizmente, onde o GNU mktemp toma o template como -t , no OSX isso é passado como argumento posicional. Em vez disso, o mktemp do OSX tem uma opção -t que significa outra coisa. A opção -t no OSX é documentada como um "prefixo" para o modelo. Ele é expandido para {prefix}.XXXXXXXX , então adiciona automaticamente o Xs (por exemplo, mktemp -d -t example poderia criar example.zEJZWCTQ no diretório temporário).

Fiquei surpreso ao descobrir que, em muitos ambientes Linux, $TMPDIR é não definido por padrão. Muitos programas CLI oferecem suporte a ele quando configurados, mas ainda precisam de um padrão para /tmp . Isso significa passar $TMPDIR/example.XXXXXXXX para mktemp ou o mkdir é perigoso porque pode produzir /example.XXXXXXXX no diretório raiz do disco local (devido a $ TMPDIR ser desconfigurado e se tornar uma string vazia).

No OSX, $TMPDIR é sempre definido e (pelo menos no shell padrão) não está definido como /tmp (que é um link simbólico para /private/tmp ), mas para /var/folders/dx/*****_*************/T . Então, o que quer que façamos para a OSX, devemos honrar esse comportamento padrão.

Concluindo, o que acabei de usar foi o criar de forma confiável um diretório temporário que funciona no Linux e no Darwin (Mac OS X), sem codificar $TMPDIR ou /tmp :

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

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

    
por 30.07.2013 / 23:59
14

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

    
por 26.01.2012 / 22:14
7

Altere --directory para -d . O primeiro é um GNU-ism, mas o GNU mktemp do coreutils também suporta -d . O mktemp no OS X é o mesmo do BSD, então -d deve ser bastante portátil entre os sistemas que realmente enviam um programa mktemp .

    
por 26.01.2012 / 20:35
4
temp_dir="$(mktemp -q -d -t "$(basename "$0").XXXXXX")"
  • mktemp para o BSD (incluindo OSX ) requer um modelo, mas permite qualquer número de X s no modelo.
  • (GNU) mktemp para o Linux não requer um modelo, no entanto, se um modelo for especificado, o número de X s deve ser 6.

Observe que -t está obsoleto para GNU mktemp , então um código mais à prova do futuro seria

temp_dir="$(mktemp -q -d -t "$(basename "$0").XXXXXX" 2>/dev/null || mktemp -q -d)"
    
por 28.05.2015 / 16:55