スクリプトの実行中に、/tmp
ディレクトリに一時ファイルを作成します。
そのスクリプトの実行後、それはそのスクリプトによって消去されます。
シェルスクリプトでそれを行う方法
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
: ...
rm "$tmpfile"
ファイルのファイル記述子を開いて削除することにより、スクリプトが終了したときに(強制終了やクラッシュを含む)ファイルが削除されたことを確認できます。ファイルは引き続き使用可能です(スクリプト用。実際には他のプロセス用ではなく/proc/$PID/fd/$FD
は、ファイル記述子が開いている限り、回避策です。ファイルシステムが閉じられると(プロセスの終了時にカーネルが自動的に行います)、ファイルシステムはファイルを削除します。
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
exec 3>"$tmpfile"
rm "$tmpfile"
: ...
echo foo >&3
mktemp
を使用して一時ファイルを作成します
temp_file=$(mktemp)
または、一時的なディレクトリを作成するには:
temp_dir=$(mktemp -d)
スクリプトの最後で、一時ファイルまたは一時ディレクトリを削除する必要があります
rm ${temp_file}
rm -R ${temp_dir}
mktemp
は、/tmp
ディレクトリまたは--tmpdir
引数で指定されたディレクトリにファイルを作成します。
mktemp があるシステムを使用している場合は、それを他の回答として使用する必要があります。
POSIXツールチェストの場合:
umask 0177
tmpfile=/tmp/"$0"."$$"."$(awk 'BEGIN {srand();printf "%d\n", Rand() * 10^10}')"
trap 'rm -f -- "$tmpfile"' INT TERM HUP EXIT
: > "$tmpfile"
一部のシェルには機能が組み込まれています。
zsh
の=(...)
形式のプロセス置換は、一時ファイルを使用します。たとえば、=(echo test)
は、_test\n
_を含む一時ファイルのパスに展開されます。
_$ {cat $file; ls -l /dev/fd/3; echo test2 >&3; cat $file} 3<> ${file::==(echo test)}
test
lrwx------ 1 stephane stephane 64 Jan 30 11:19 /dev/fd/3 -> /tmp/zshMLbER0
test2
_
コマンドが完了すると、そのファイルは自動的に削除されます。
bash
およびzsh
のhere-filesまたはhere-stringsは、削除された一時ファイルとして実装されます。
だからあなたがするなら:
_exec 3<<< test
_
ファイル記述子3は、_test\n
_を含む削除済み一時ファイルに接続されています。
次の方法でコンテンツを取得できます。
_cat <&3
_
Linuxの場合、_/dev/fd/3
_を介してそのファイルを読み書きすることもできますが、bashバージョン5以降では、まず書き込み権限を復元する必要があります(bashは明示的に削除します)。
_$ exec 3<<< test
$ cat <&3
test
$ chmod u+w /dev/fd/3 # only needed in bash 5+
$ echo foo > /dev/fd/3
$ cat /dev/fd/3
foo
_
(他の一部のシェルはパイプを使用しますが、ヒアドキュメントが空の場合は_/dev/null
_を使用する場合があります)。
mktemp
POSIXユーティリティはありません。ただし、POSIXは mkstemp(template)
C API を指定し、_m4
_標準ユーティリティは同じ名前のmkstemp()
m4関数でそのAPIを公開します。
mkstemp()
は、関数が呼び出されたときに存在しないことが保証されたランダムな部分を含むファイル名を提供します。レースなしでパーミッション0600のファイルを作成します。
だから、あなたは行うことができます:
_tmpfile=$(
echo 'mkstemp(template)' |
m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit
_
ただし、終了時にクリーンアップを処理する必要があることに注意してください。ただし、ファイルの書き込みと読み取りを一定回数行うだけの場合は、here-doc/here-のように作成した直後にファイルを開いて削除できます。上記の文字列アプローチ:
_tmpfile=$(
echo 'mkstemp(template)' |
m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit
# open once for writing, twice for reading:
exec 3> "$tempfile" 4< "$tempfile" 5< "$tempfile"
rm -f -- "$tmpfile"
cmd >&3 # store something in the temp file
exec 3>&- # fd no longer needed
# read the content twice:
cat <&4
cat <&5
_
ファイルを1回読み取り用に開き、2回の読み取りの間に巻き戻すことができますが、その巻き戻しを行うことができるPOSIXユーティリティ(lseek()
)がないため、POSIXスクリプトで移植することはできません(zsh
(sysseek
組み込み)と_ksh93
_(<#((...))
演算子)でも実行できます)。
これは、Hauke Lagingのラインで少し改善された回答です。
#!/bin/bash
tmpfile=$(mktemp) # Create a temporal file in the default temporal folder of the system
# Lets do some magic for the tmpfile to be removed when this script ends, even if it crashes
exec {FD_W}>"$tmpfile" # Create file descriptor for writing, using first number available
exec {FD_R}<"$tmpfile" # Create file descriptor for reading, using first number available
rm "$tmpfile" # Delete the file, but file descriptors keep available for this script
# Now it is possible to work with the temporal file
echo foo >&$FD_W
echo bar >&$FD_W # Note that file descriptor always concatenates, not overwrites
cat <&$FD_R
通常、一時ファイルを使用するワークフローは、テストしているbashスクリプトが原因です。私はそれをtee
上げて、それが機能していることを確認し、プロセスの次の反復のために出力を保存したいと思っています。 tmp
というファイルを作成しました
#!/bin/bash
echo $(mktemp /tmp/$(date +"%Y-%m-%d_%T_XXXXXX"))
私はそれを次のように使用できるように
$ some_command --with --lots --of --stuff | tee $(tmp)
ランダムな値の前にフォーマットされた日時が好きな理由は、簡単に作成したtmpファイルを見つけることができるためです。次回は何に名前を付けるかについて考える必要がありません(そして、ダンスクリプトを取得することに集中する必要はありません)。動作するように)。