Поиск правильного каталога TMP на нескольких платформах

46

У меня есть скрипт, который должен создавать временные файлы для своей работы и очищать после себя. Мой вопрос о том, чтобы найти правильный базовый каталог для временных файлов.

Скрипт должен работать на нескольких платформах: Git Bash (Windows), Solaris, Linux, OSX. На каждой платформе предпочтительный временный каталог выражается по-разному:

  • Windows: %TMP%(и возможно %TEMP%)
  • OSX: $TMPDIR
  • Linux, UNIX: должен быть, $TMPDIRно, похоже, не установлен на нескольких системах, которые я пробовал

Итак, в моем сценарии я добавил этот шаблон:

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

Это кажется слишком утомительным. Есть ли способ лучше?

Прекратить постоянный вред Монике
источник
6
Просто используйте ${TMPDIR-/tmp}на Unix-лайки. TMPDIRесть (система или администратор или пользователь), чтобы сказать вам, когда не следует использовать /tmpдля временных файлов.
Стефан Шазелас

Ответы:

72

Несколько более портативный способ обработки временных файлов - использовать mktemp. Он создаст временные файлы и вернет вам их пути. Например:

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

Вы можете использовать его в скрипте довольно легко:

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

Читая справочную страницу, вы сможете настроить параметры в соответствии с вашими потребностями. Например:

  • -d создает каталог вместо файла.
  • -u генерирует имя, но не создает ничего.

Используя его, -uвы можете легко получить временный каталог с помощью ...

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

Более подробная информация mktempдоступна здесь .

Редактирование, касающееся Mac OS X: я никогда не использовал систему Mac OSX, но согласно комментарию Tyilo ниже, похоже, что Mac OSX mktempтребует , чтобы вы предоставили шаблон (который является необязательным аргументом в Linux). Цитирование:

Например, шаблон может быть любым именем файла, к которому добавлено некоторое число «X» /tmp/temp.XXXX. Конечные «X» заменяются номером текущего процесса и / или уникальной комбинацией букв. Количество уникальных имен файлов, которые mktemp может вернуть, зависит от количества предоставленных «X»; шесть «X» приведут к выбору mktemp 1 из 56800235584 (62 ** 6) возможных имен файлов.

Страница руководства также говорит, что эта реализация основана на странице руководства OpenBSD mktemp. Поэтому подобное расхождение может наблюдаться и пользователями OpenBSD и FreeBSD (см. Раздел « История »).

Теперь, как вы, вероятно, заметили, для этого необходимо указать полный путь к файлу, включая временный каталог, который вы ищете в своем вопросе. Эта небольшая проблема может быть решена с помощью -tпереключателя. В то время как эта опция, кажется, требует аргумента ( prefix), кажется, что она mktempполагается $TMPDIRпри необходимости.

В общем, вы должны быть в состоянии получить тот же результат, что и выше, используя ...

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

Буду признателен за любые отзывы пользователей Mac OS X, так как я не могу самостоятельно протестировать это решение.

Джон У. Смит
источник
ФП рассмотрела эту проблему в удаленном сейчас комментарии; Боюсь, я не могу дать ответ для систем, которые требуют gitbashполучить интерфейс оболочки, следовательно, мой "немного". Я на самом деле не смогу сказать, где временные файлы хранятся в системе Windows ...
Джон У. Смит,
1
То же самое. Некоторые сумасшедшие c:\User\Name\..............\stuff. И их, наверное, 100. Тем не менее, некоторые дистрибутивы Linux приближаются к тому же уровню безумия в /var. Мне просто было любопытно. Мне показалось странным сказать, что это все - по моему опыту разочарование очень переносимо, а удобство меньше. В любом случае, очень хороший ответ.
mikeserv
1
Примерно год назад я написал сценарий Bash для управления файлами точек восстановления Windows, которые работают на Windows 2000 и WinXP (более поздние версии обрабатывают эти вещи по-разному). Мой скрипт использует WINDOWS/Tempили Windows/Tempкак каталог по умолчанию для своих временных файлов; этот каталог также существует на компьютерах с Windows 7. Но мой сценарий позволяет пользователю указать альтернативный временный каталог в командной строке.
PM 2Ring
Это не сработает в OS X, так как вы должны предоставить шаблон mktemp.
Tyilo
1
Так как El Capitan, mktempпросто работает: simple mktempвозвращает файл и mktemp -dвозвращает каталог; шаблоны не требуются. Руководство не обновляется , хотя.
Франклин Ю
9

Если вы ищете то же самое в меньшем количестве строк ...

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

Вы могли бы написать это в одном.

frostschutz
источник
Вы, вероятно, также должны проверить, если это доступно для записи.
frostschutz
@janos: А если ничего не помогает, попросите пользователя указать путь к временным файлам или разрешите ему указать путь в командной строке.
PM 2Ring
6

Вы могли бы сделать:

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

Оболочка должна либо найти исполняемый каталог в одном из 4 вариантов, либо завершить работу со значительной ошибкой. Тем не менее, POSIX определяет $TMPDIRпеременную (для систем XCU) :

TMPDIR Эта переменная должна представлять путь к каталогу, доступному для программ, которым требуется место для создания временных файлов.

Это также требует /tmpпути.

mikeserv
источник
1
Это единственный правильный ответ здесь ИМО. Не знаю, что он делает, сидя внизу без голосов ...
Грэм,
2
@Graeme: может быть, потому что это совершенно нечитаемо?
SSC
Я проголосовал, но потом отказался - да, этот ответ - беспорядок. Кажется, он идет по полезному пути, но не совсем понятно, что пытается сделать фрагмент кода - первая строка - комментарий, а вторая - нет. одна ошибка (во всяком случае, в bash). Мог бы использовать какую-то работу.
Дон Хэтч
О, я вижу, первая версия ответа была более ясной (все же ошибка во 2-й строке, если вы действительно пытаетесь запустить ее) ... а затем ряд изменений полностью уничтожил пример кода, так что теперь это чепуха. Можно использовать еще один или два прохода :-)
Дон Хэтч