Linux / コマンド / mktemp - 安全な一時ファイルとディレクトリの作成
mktempは予測できない固有の名前で、テンポラリファイルやディレクトリを原子的に作成し、そのパスを出力します。プロセスIDを付けた名前を自分で作る方法と比べて、名前の衝突やシンボリックリンク競合の条件を減らすことができます。
この記事では、テンプレートの使用方法、テンポラリディレクトリの作成、TMPDIRと場所の選択、シェルのtrapを使用した整理、避けるべき-uの使用方法について解説します。
mktempコマンドとは?
mktempはテンプレートの連続したXをランダムな文字に置き換え、その名前のファイルやディレクトリを実際に作成した後、パスを出力します。テンプレートを指定する場合、最後のパス構成要素に通常3つ以上の連続したXが必要です。出力されたパスには空白が含まれる場合があるため、必ず引用符で囲んで使用してください。
基本的な文法
mktemp [オプション] [テンプレート]
ファイル名やパスに空白がある場合は引用符で囲み、ハイフンで始まる名前は可能であれば--の後に指定します。サポートされるオプションはディストリビューションとGNU Coreutilsのバージョンによって異なる場合があるため、mktemp --helpとman mktempで現在のシステムの説明を確認してください。
mktempの基本的な使用方法
テンポラリファイルを作成する
テンプレートを省略すると、システムの一時ディレクトリポリシーに従って固有のファイルを作成し、パスを出力します。
tmp_file=$(mktemp) || exit 1
printf '%s\n' "$tmp_file"
名前の形式を指定する
最後の連続したXが固有の文字列に置き換わります。拡張子が必要な場合はテンプレートの後に付けるか、--suffixを使用します。
mktemp report-XXXXXXXX.csv
mktemp --suffix=.log app-XXXXXXXX
一時ディレクトリを作成する
-dはファイルの代わりに、現在のユーザーのみがアクセスできる一時ディレクトリを作成します。umask は作成時の権限を制限する設定で、厳しい値なら権限はさらに減ります。
tmp_dir=$(mktemp -d) || exit 1
printf '%s\n' "$tmp_dir"
実際の生成パスを確認する
mktempは安全に作成した一時ファイルのパスを標準出力に返します。名前を推測して作成したり、-uの結果だけを信用しないでください。
tmpfile=$(mktemp) || exit 1
printf '%s\n' "$tmpfile"
test -f "$tmpfile"
echo $?
出力は一時パスの1行と0です。一時パスの文字列は実行ごとに異なります。作業が終わったら正確に作成したファイルか確認し、引数に引用符で囲んだ変数パスを整理してください。
主なオプション
| オプション | 説明 |
|---|---|
-d, --directory |
一時ファイルではなくディレクトリを作成します。 |
-p DIR, --tmpdir=DIR |
テンプレートを指定したディレクトリを基準として使用します。 |
--tmpdir |
引数なしで使用するとTMPDIRまたはデフォルトの一時ディレクトリを使用します。 |
--suffix=SUFFIX |
生成名の後に接尾辞を付けます。 |
-q, --quiet |
生成失敗の診断を隠しますが、終了状態は維持します。 |
-u, --dry-run |
名前だけを出力し、作成はしません。競合条件のため、セキュリティ用途には使用してはいけません。 |
長いオプションは意味を把握しやすく、スクリプトの確認にも役立ちます。ただし、移植性が重要なスクリプトでは対象システムがその GNU 拡張オプションをサポートしているかをまず確認してください。
実践的活用例
trapで一時ファイルを整理する
以下はBashスクリプトとして使います。cleanup-file.sh に保存して bash cleanup-file.sh と実行してください。作成に成功したら EXIT で後片付けし、HUP・INT・TERM を受けた場合は終了してから同じ後片付けを行います。削除だけして処理を続ける形にはしません。SIGKILL による強制終了や停電ではtrapが実行されないため、必ず消える保証ではありません。
tmp_file=$(mktemp) || exit 1
trap 'rm -f -- "$tmp_file"' EXIT
trap 'exit 129' HUP
trap 'exit 130' INT
trap 'exit 143' TERM
printf '%s\n' 'temporary data' > "$tmp_file"
一時作業ディレクトリを使用する
複数の中間ファイルが必要なら、一時ディレクトリを作り、その中で固定名を使うと管理しやすくなります。以下も独立したBashスクリプトとして実行します。input と output はパスの変数で、この例だけではファイルは作りません。後続の処理でこの配下を使い、work_dir は再代入せず、他者が配下を変更できない作業場所に限定してください。
work_dir=$(mktemp -d) || exit 1
trap 'rm -rf -- "$work_dir"' EXIT
trap 'exit 129' HUP
trap 'exit 130' INT
trap 'exit 143' TERM
input=$work_dir/input
output=$work_dir/output
希望する親ディレクトリを選択する
同じファイルシステムで原子的な名前変更が必要な場合や、容量・セキュリティポリシーが異なる場合は-pで場所を指定します。親ディレクトリは事前に存在する必要があります。mkdirによるディレクトリ作成で書き込める場所を準備し、秘密情報を扱う場合は親の所有者やアクセス権も確認します。
mkdir -p "$HOME/.cache/myapp"
cache_file=$(mktemp -p "$HOME/.cache/myapp" cache-XXXXXXXX) || exit 1
mktempと関連コマンドの比較
| コマンド・方法 | 主な役割 | 適した状況 |
|---|---|---|
mktemp |
一意の名前を作成し、すぐに項目を生成 | 安全な一時ファイル・ディレクトリ |
touch |
指定した固定名のファイルを作成 | 衝突のリスクがない一般ファイル |
mkdir |
指定した固定名のディレクトリを作成 | 永続的であるか、事前に指定したパス |
mktemp -u |
使用されていない名前のみを出力 | セキュリティファイルの作成には不適切 |
使用する際の注意点
-u 結果でファイルを作らない
名前を出力した後、実際にファイルを作成する間に他のプロセスが同じパスを占有する可能性があります。テンポラリファイルは-uなしでmktempが直接作成するようにしてください。
整理コマンドの変数を引用符で囲む
空の値や空白を含むパスが誤って展開されると、思わぬファイルを削除する可能性があります。作成の成功を確認し、rm -- "$変数"のように使用してください。
機密データの保存場所を確認する
一時ディレクトリがメモリファイルシステムなのかディスクなのか、バックアップ・スワップ・スナップショットに含まれるかどうかはシステムによって異なります。機密データポリシーを別途確認してください。
FAQ
プロセスIDを付けた一時ファイル名よりmktempの方が安全な理由は何ですか?
予測しにくい名前を選び、ファイル作成までを一段階で行うことで、名前の先取りやシンボリックリンクの競合条件を減らすためです。
一時ディレクトリを作るにはどうすればよいですか?
mktemp -dを使用し、返されたパスを変数に保存した後、引用符で囲んで使用してください。
作成した一時ファイルは自動で削除されますか?
一般的に自動では削除されません。シェルスクリプトではtrapで終了時に整理するよう登録してください。
TMPDIRはいつ使用されますか?
--tmpdir の使用やテンプレートを省略した場合に、一時ファイルを置く場所を選択するために使用できます。実際の動作は、インストールされているバージョンのヘルプで確認してください。




