Я хотел добавить уточнение к ответу @Mario Mueller, так как он зависит от возможных условий гонки, однако я считаю, что следующее не должно быть:
function tempdir(int $mode = 0700): string {
do { $tmp = sys_get_temp_dir() . '/' . mt_rand(); }
while (!@mkdir($tmp, $mode));
return $tmp;
}
Это работает, потому что mkdir
возвращает false
, если $tmp
уже существует, в результате чего цикл повторяется и используется другое имя.
Обратите также внимание, что я добавил обработку для $mode
, по умолчанию, которая обеспечивает доступ к каталогу только для текущего пользователя, так как mkdir
по умолчанию 0777
в противном случае.
Настоятельно рекомендуется использовать функцию завершения работы, чтобы обеспечить удаление каталога, когда он больше не нужен, даже если ваш скрипт завершает работу непредвиденным образом *. Чтобы облегчить это, полная функция, которую я использую, делает это автоматически, если аргумент $auto_delete
не установлен в false
.
// Deletes a non-empty directory
function destroydir(string $dir): bool {
if (!is_dir($dir)) { return false; }
$files = array_diff(scandir($dir), ['.', '..']);
foreach ($files as $file) {
if (is_dir("$dir/$file")) { destroydir("$dir/$file"); }
else { unlink("$dir/$file"); }
}
return rmdir($dir);
}
function tempdir(int $mode = 0700, bool $auto_delete = true): string {
do { $tmp = sys_get_temp_dir() . '/' . mt_rand(); }
while (!@mkdir($tmp, $mode));
if ($auto_delete) {
register_shutdown_function(function() use ($tmp) { destroydir($tmp); });
}
return $tmp;
}
Это означает, что по умолчанию любой временный каталог, созданный tempdir()
, будет иметь разрешения 0700
и будет автоматически удален (вместе с его содержимым), когда ваш скрипт завершится.
ПРИМЕЧАНИЕ : * Это может быть не так, если сценарий убит, для этого вам может потребоваться также регистрация обработчика сигнала.