Исправить или альтернатива для mktemp в OS X

73

Я смотрю на bash-скрипт, который кто-то еще написал, который использует mktemp:

TEMP=`mktemp --directory`

Однако эта строка не работает на моей машине (OS X 10.6).

Как бы я исправил эту строку, чтобы она была совместима с кросс-un * x-like-platform? РЕДАКТИРОВАТЬ: альтернативная команда будет также достаточно.

mindeavor.
источник

Ответы:

109

Ниже приведено то, что я использовал для надежного создания временного каталога, который работает как в Linux, так и в Darwin (все версии до Mac OS X 10.11), без жесткого кодирования $TMPDIRили /tmp:

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

Фон:

Команда GNU mktemp не требует аргументов. Обычный mktempбудет работать и создает временный файл во временном каталоге системы.

Обычный mktemp -dсоздаст каталог вместо файла, который вы хотели бы использовать в Linux.

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

По умолчанию GNU mktemp использует шаблон tmp.XXXXXXXXXXдля имени подкаталога (или файла). Чтобы настроить этот шаблон, -tможно использовать эту опцию.

Mktemp в OSX не имеет шаблона по умолчанию и требует указания шаблона. К сожалению, где GNU mktemp принимает шаблон в качестве -tопции, в OSX это передается как позиционный аргумент. Вместо этого в OSX mktemp есть -tопция, которая означает что-то еще. -tВариант на OSX документирован как «префикс» для шаблона. Он расширен до {prefix}.XXXXXXXX, поэтому он добавляет к нему X автоматически (например, mktemp -d -t exampleможет создать example.zEJZWCTQво временном каталоге).

Я с удивлением обнаружил , что во многих средах Linux, $TMPDIRэто не устанавливается по умолчанию. Многие программы CLI поддерживают его, когда они установлены, но все еще нуждаются в значении по умолчанию для /tmp. Это означает, что переход $TMPDIR/example.XXXXXXXXк mktemp или mkdir опасен, поскольку он может появиться /example.XXXXXXXXв корневом каталоге локального диска (из-за того, что $ TMPDIR не установлен и становится пустой строкой).

В OSX $TMPDIRвсегда устанавливается и (по крайней мере в оболочке по умолчанию) устанавливается не на /tmp(что является символической ссылкой /private/tmp), а на /var/folders/dx/*****_*************/T. Поэтому, что бы мы ни делали для OSX, следует соблюдать это поведение по умолчанию.

В заключение, следующее , что я в конечном итоге использовала , чтобы надежно создать временный каталог , который работает как на Linux и Darwin (Mac OS X), без жесткого кодирования либо $TMPDIRили /tmp:

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

Первая часть для Linux. Эта команда не удастся выполнить в Darwin (Mac OS X) с кодом ошибки, 1ответившим «use: ...». Вот почему мы игнорируем stderr и вместо этого запускаем вариант Mac. mytmpdirПрефикс используется только на Mac (где требуется , чтобы установить , что опция).

Тимо Тиххоф
источник
12
Очень круто. Иногда OS X отличное поведение раздражает.
Therealmarv
6
@therealmarv Я бы лучше сказал, всегда.
Никита Волков
10
Я только что запустил mktemp -dна OS X 10.11.5 El Capitan, и все заработало, как и ожидалось file $(mktemp -d):: /var/folders/j4/htlnmbf97vlcdszj7_x8g0vh4k3_fp/T/tmp.JXmsrQnL: directory
Heath Borders
2
Ага. Я был удивлен, как и вы, что это Just Worked ™.
Хит Бордерс
1
Также, если вы работаете mktemp -d -t 'mytmpdir'в Linux (протестировано с mktempfrom coreutils 8.26), оно работает как положено.
15

Вы должны предоставить шаблон. mktemp -d /tmp/foo.XXXXдолжно сработать. Я никогда не видел --directory. Предполагается, --что это расширение GNU.

Кайл Джонс
источник
6
Если вы хотите использовать, $TMPDIRкогда доступно, делайте mktemp -d "${TMPDIR:-/tmp}"/foo.XXXX. Это работает в bash на Mac и dash на Debian, поэтому кажется переносимым.
Том Андерсон
9

Изменить --directoryна -d. Первый - это GNU-изм, но GNU mktempот coreutils также поддерживает -d. mktempВ OS X такое же , как от BSD, так что -dдолжно быть довольно переносимым между системами , которые фактически поставляются в mktempпрограмму.

Джеймс Снерингер
источник
Я только что попробовал mktemp -d, и это тоже не работает.
Миндавор.
1
Кайл имеет полный ответ. На mktempOS X требуется шаблон. Используемый скрипт предполагает использование соглашений GNU, в котором используется шаблон по умолчанию, если он не указан.
Джеймс Снерингер
Проблема в том, что unix ожидает, XXXXXчто он будет предоставлен в шаблоне, где, поскольку OS X не уверен, есть ли совместимый флаг шаблона?
user3467349
2
mktempна OS X 10.11.5 El Capitan работает для меня file $(mktemp -d)::/var/folders/j4/htlnmbf97vlcdszj7_x8g0vh4k3_fp/T/tmp.JXmsrQnL: directory
Хит Границы
4
temp_dir="$(mktemp -q -d -t "$(basename "$0").XXXXXX")"
  • mktempдля BSD (включая OSX ) требуется шаблон, но он допускает любое количество Xs в шаблоне.
  • (GNU) mktempдля Linux не требует шаблона, однако, если шаблон указан, то число Xs должно быть 6.

Обратите внимание, что -tэто не рекомендуется для GNUmktemp , поэтому более перспективный код будет

temp_dir="$(mktemp -q -d -t "$(basename "$0").XXXXXX" 2>/dev/null || mktemp -q -d)"
go2null
источник