Як створити тимчасовий каталог?


229

Я використовую для створення tempfile, видалення та відтворення його як каталог:

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

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

Відповіді:


341

Використовуйте mktemp -d. Він створює тимчасовий каталог із випадковим іменем та гарантує, що файл ще не існує. Вам потрібно пам’ятати, щоб видалити каталог після його використання.


25
Мені довелося скористатисяmktemp -d -t <prefix>
Heath Borders

17
Це ОС X проти Linux. Дивіться це запитання для версії, яка працює на обох: unix.stackexchange.com/questions/30091/…
jwhitlock

2
Також дивіться відповідь Ортвіна нижче, оскільки це гарантує також, що очищення зроблено.
Mathiasdm

5
Чому ви говорите "Вам потрібно пам’ятати, щоб видалити каталог після його використання."? Хіба це нічим не перешкоджає використанню темп-каталогу?
МК Сафі

73

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

Функція очищення виконується на 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
Добре, оновив сценарій, щоб перевірити, чи можна створити темп-реж.
Ortwin Angermeier

1
@madfriend насправді? якщо mktempне вдасться, WORK_DIRбуде порожнім, тобто команда буде просто rm -rfбез аргументу. Я не використовую FreeBSD, але я був би дуже здивований, якщо rm -rfбуло б рівнозначноrm -rf .
jbg

@jbg так, мені здається дивним і зараз - це не повинно бути справді великою проблемою. Я, можливо, переробив стару версію цього сценарію, щоб шлях до тимчасового каталогу був обчислений відносно поточного каталогу, що призвело до <s> вимирання людства </s> видалення поточного каталогу.
madfriend

1
Для того, щоб зробити його краще, ви можете уникнути марної каталог або по крайней мере , містити проблему в директорії , використовуючи рішення , в якому ви робите: 1. TMPWORKDIR=$(basename 'mktemp -d -p /tmp/git/')а потім 2. rmdir /tmp/git/"${TMPWORKDIR}". Якщо змінна зараз порожня, ви все одно повернетесь /tmp/git/не до всієї системи. Розгляньте щось подібне у відповіді, і я з радістю погодиться. ;)
Д-р Беко

64

Мій улюблений однопластовий для цього

cd $(mktemp -d)

10

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
Андрій Щербаков

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

1
Хоча це цікаве рішення для усунення помилок, було б непогано пояснити переваги та можливі недоліки.
Мерфі

1.) -dперевірки на каталоги. 2.) Закінчення вже є типовим для цих сигналів.
припинення
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.