一時ディレクトリを作成するには?


229

私はを作成してtempfile削除し、ディレクトリとして再作成するために使用します。

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

問題は、あるプロセスのXrm -f X、直前にtempfileを誤って実行した場合、別のプロセスが同じ名前を取得する可能性があることmkdir Xです。

回答:


341

を使用しmktemp -dます。ランダムな名前で一時ディレクトリを作成し、ファイルがまだ存在していないことを確認します。ただし、使用後は必ずディレクトリを削除する必要があります。


25
私は使用しなければなりませんでしたmktemp -d -t <prefix>
ヒースボーダー

17
これはOS XとLinuxの違いです。:両方で動作バージョンのため、この質問を参照してください unix.stackexchange.com/questions/30091/...
jwhitlock

2
また、以下のOrtwinによる回答を参照してください。これにより、クリーンアップも確実に行われます。
Mathiasdm 2016年

5
なぜ「それを使用した後でもディレクトリを削除することを覚えておく必要がある」と言うのですか?それは一時ディレクトリを使用する目的を少し損ないませんか?
MK Safi 2017

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の注意!FreeBSD上でmktempのは、-pオプションを持っていない、とcleanupされます現在のディレクトリを-rf RM!
マッドフレンド2017年

1
良い点、スクリプトを更新して、一時ディレクトリを作成できるかどうかを確認しました。
Ortwin Angermeier 2017年

1
@madfriend本当に?場合は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/、システム全体にフォールバックしません。答えでこのようなものを検討してください、そして私は喜んで同意します。;)
Dr Beco

64

このための私のお気に入りのワンライナーは

cd $(mktemp -d)

10
rm $(pwd)?:P
Arran Cudbard-Bell 2014

19
また便利:pushd $(mktemp -d)...popd
Ponkadoodle 2014

4
@ ArranCudbard-Bellのはずですrm -r $(pwd)
piggybox 2015

31
@piggybox率直に言って、私はの使用に非常に慎重になるでしょうrm -r $(pwd)。何らかの理由で一時ディレクトリの作成が失敗する可能性を考慮してください(おそらく/ tmpファイルシステムがいっぱいであるか、エラーのために読み取り専用で再マウントされていますか?)。次に、ユーザーのホームディレクトリへの変更をcd $(mktemp -d)評価します。cdこの変更は、後で削除されます。
ジュール

1
それは安全かもしれませんif pushd $(mktemp -d || echo BADMPDIR); then ........ ; rm -r $(pwd); popd; fi
AndreyS Scherbakov

9

次のスニペットは、一時ディレクトリ(-d)を安全に作成し、その名前をに保存しTMPDIRます。(TMPDIR変数の使用例は、後で変更される可能性のある元のファイルを格納するために使用されるコードの後半に示されています。)

最初のtrap行はexit 1、指定された信号のいずれかが受信されたときにコマンドを実行します。2 trap行目は、$TMPDIRonプログラムの出口(正常と異常の両方)を削除(クリーンアップ)します。確認後、これらのトラップを初期化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.)終了はすでにこれらの信号のデフォルトです。
ceving
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.