Как создать временный каталог?

229

Я использую, чтобы создать tempfile, удалить его и воссоздать его как каталог:

tmpnam=`tempfile`
rm -f $tmpnam
mkdir "$tmpnam"

Проблема в том, что другой процесс может получить такое же имя X, если он случайно запускает tempfile после одного процесса rm -f Xи непосредственно перед ним mkdir X.

Xiè Jìléi
источник

Ответы:

341

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

moinudin
источник
25
Я должен был использоватьmktemp -d -t <prefix>
Хит Бордерс
17
Это OS X против Linux. Посмотрите этот вопрос для версии, которая работает на обоих: unix.stackexchange.com/questions/30091/…
jwhitlock
2
Кроме того, смотрите ответ ниже Ортвина, поскольку это гарантирует, что очистка также сделана.
Mathiasdm
5
Почему вы говорите: «Вы должны помнить, чтобы удалить каталог после его использования.»? Разве это не побеждает цель использования временного каталога?
МК Сафи
73

Для более надежного решения я использую что-то вроде следующего. Таким образом, временный каталог всегда будет удаляться после выхода из скрипта.

Функция очистки выполняется по EXITсигналу. Это гарантирует, что функция очистки всегда вызывается, даже если скрипт где-то прерывается.

#!/bin/bash    

# the directory of the script
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

# the temp directory used, within $DIR
# omit the -p parameter to create a temporal directory in the default location
WORK_DIR=`mktemp -d -p "$DIR"`

# check if tmp dir was created
if [[ ! "$WORK_DIR" || ! -d "$WORK_DIR" ]]; then
  echo "Could not create temp dir"
  exit 1
fi

# deletes the temp directory
function cleanup {      
  rm -rf "$WORK_DIR"
  echo "Deleted temp working directory $WORK_DIR"
}

# register the cleanup function to be called on the EXIT signal
trap cleanup EXIT

# implementation of script starts here
...

Каталог скриптов bash отсюда .

Баш ловушки .

Ортвин Ангермейер
источник
26
FreeBSD Осторожно! mktemp во FreeBSD не имеет опции -p и cleanupбудет rm -rf вашей текущей директории!
сумасшедший
1
Хороший вопрос, обновил скрипт, чтобы проверить, можно ли создать временный каталог.
Ортвин Ангермейер,
1
@ действительно друг? в случае mktempнеудачи WORK_DIRбудет пустым, то есть команда будет rm -rfбез аргумента. Я не использую FreeBSD, но я был бы очень удивлен, если бы это rm -rfбыло эквивалентноrm -rf .
jbg
@jbg да, мне это тоже кажется странным - это не должно быть большой проблемой. Я мог бы подправить старую версию этого сценария, чтобы путь к временному каталогу был рассчитан относительно текущего каталога, что привело к <s> вымиранию человечества </ s> удалению текущего каталога.
сумасшедший
1
Чтобы сделать это лучше, вы можете избежать пустого каталога или, по крайней мере, содержать проблему в каталоге, используя решение, в котором вы делаете: 1. TMPWORKDIR=$(basename 'mktemp -d -p /tmp/git/')а затем 2 rmdir /tmp/git/"${TMPWORKDIR}".. Если переменная сейчас пуста, вы все равно вернетесь к /tmp/git/не всей системе. Примите во внимание что-то подобное в ответе, и я с радостью соглашусь. ;)
Доктор Беко
64

Мой любимый лайнер для этого

cd $(mktemp -d)
Эммет Батлер
источник
10
а rm $(pwd)? : P
Арран Кудбард-Белл
19
Также полезно: pushd $(mktemp -d)...popd
Ponkadoodle
4
@ ArranCudbard-Bell должен бытьrm -r $(pwd)
piggybox
31
@piggybox Честно говоря, я буду очень осторожен в использовании rm -r $(pwd). Рассмотрите возможность того, что создание временного каталога по какой-либо причине завершится неудачно (может быть, файловая система / tmp переполнена или перемонтирована только для чтения из-за ошибки?); затем cd $(mktemp -d)оценит, cdкакие изменения в домашнем каталоге пользователя будут впоследствии удалены.
Жюль
1
Это может быть безопасно сif pushd $(mktemp -d || echo BADMPDIR); then ........ ; rm -r $(pwd); popd; fi
AndreyS Щербаков
9

Следующий фрагмент безопасно создаст временный каталог ( -d) и сохранит его имя в TMPDIR. (Пример использования TMPDIRпеременной показан ниже в коде, где она используется для хранения исходных файлов, которые могут быть изменены).

Первая trapстрока выполняет exit 1команду при получении любого из указанных сигналов . Вторая trapстрока удаляет (очищает) выход $TMPDIRиз программы (как нормальный, так и ненормальный). Мы инициализируем эти ловушки после того, как проверим, что mkdir -dудалось избежать случайного выполнения ловушки выхода с $TMPDIRнеизвестным состоянием.

#!/bin/bash

# Create a temporary directory and store its name in a variable ...
TMPDIR=$(mktemp -d)

# Bail out if the temp directory wasn't created successfully.
if [ ! -e $TMPDIR ]; then
    >&2 echo "Failed to create temp directory"
    exit 1
fi

# Make sure it gets removed even if the script exits abnormally.
trap "exit 1"           HUP INT PIPE QUIT TERM
trap 'rm -rf "$TMPDIR"' EXIT

# Example use of TMPDIR:
for f in *.csv; do
    cp "$f" "$TMPDIR"
    # remove duplicate lines but keep order
    perl -ne 'print if ++$k{$_}==1' "$TMPDIR/$f" > "$f"
done
jreisinger
источник
1
Хотя это интересное решение для обработки ошибок, было бы неплохо немного пояснить преимущества и возможные недостатки.
Мерфи
1.) -dпроверяет каталоги. 2.) Завершение уже по умолчанию для этих сигналов.
выступление