web-dev-qa-db-ja.com

OS Xでのmktempの修正または代替

私は、誰かがmktempを使用して書いたbashスクリプトを見ています。

TEMP=`mktemp --directory`

ただし、この行は私のマシン(OS X 10.6)では機能しません。

この行を修正して、クロスun * xのようなプラットフォームと互換性を持たせるにはどうすればよいですか? 編集:別のコマンドでも十分です。

78
soundly_typed

以下は、$TMPDIRまたは/tmpをハードコーディングせずに、LinuxとDarwin(Mac OS X 10.11より前のすべてのバージョン)の両方で動作する一時ディレクトリを確実に作成するために使用したものです。

mytmpdir=$(mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir')

バックグラウンド:

GNU mktempコマンドは引数を必要としません。プレーンmktempは機能し、システムの一時ディレクトリに一時ファイルを作成します。

単純なmktemp -dは、ファイルの代わりにディレクトリを作成します。これは、Linuxで使用したいものです。

(gnu-coreutils)$ man mktemp
> ..
> If DIR is not specified, uses $TMPDIR if set, else /tmp.
> ..

デフォルトでは、GNU mktempはサブディレクトリ(またはファイル)の名前にテンプレートtmp.XXXXXXXXXXを使用します。このテンプレートをカスタマイズするには、-tオプションを使用できます。

OSXのmktempにはデフォルトのテンプレートがなく、テンプレートを指定する必要があります。残念ながら、GNU= mktempは、テンプレートを-tオプションとして受け取ります。OSXでは、これは位置引数として渡されます。代わりに、OSXのmktempには、何か別の意味を持つ-tオプションがあります。OSXの-tオプションは、ドキュメント化されていますテンプレートの「プレフィックス」として。これは{prefix}.XXXXXXXXに展開されるため、Xが自動的に追加されます(たとえば、mktemp -d -t exampleは一時ディレクトリにexample.zEJZWCTQを作成できます)。

多くのLinux環境では、$TMPDIRがデフォルトで設定されていないことを知って驚いた。多くのCLIプログラムは設定時にそれをサポートしますが、それでも/tmpのデフォルトが必要です。つまり、$TMPDIR/example.XXXXXXXXをmktempまたはmkdirに渡すことは危険です。これは、ローカルディスクのルートディレクトリに/example.XXXXXXXXを生成する可能性があるためです($ TMPDIRが設定解除され、空の文字列)。

OSXでは、$TMPDIRは常に設定され、(少なくともデフォルトのシェルでは)/tmp/private/tmpへのシンボリックリンク)ではなく/var/folders/dx/*****_*************/Tに設定されます。したがって、OSXに対して行うことは何でも、そのデフォルトの動作を尊重する必要があります。

結論として、以下は最終的にLinuxとDarwinの両方で機能する一時ディレクトリを確実に作成するために使用したものです(Mac OS X)、ハードコーディングなし$TMPDIRまたは/tmpのいずれか:

mytmpdir=$(mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir')

最初の部分はLinux用です。このコマンドは、「usage:...」で応答するエラーステータスコード1でDarwin(Mac OS X)で失敗します。これがstderrを無視し、代わりにMacバリアントを実行する理由です。 mytmpdirプレフィックスはMacでのみ使用されます(そのオプションを設定する必要がある場合)。

117
Timo Tijhof

テンプレートを指定する必要があります。 mktemp -d /tmp/foo.XXXXは動作するはずです。見たことがない --directory--は、これがGNU拡張機能であることを示唆しています。

15
Kyle Jones

--directory-dに変更します。前者はGNU-ismですが、coreutilsのGNU mktemp-dをサポートしています。OSXのmktempは、 BSDなので、実際にmktempプログラムを出荷するシステム間で-dはかなり移植性が高いはずです。

9
temp_dir="$(mktemp -q -d -t "$(basename "$0").XXXXXX")"
  • BSDのmktemp[〜#〜] osx [〜#〜] を含む)にはテンプレートが必要ですが、テンプレートにはXsをいくつでも含めることができます。
  • (GNU)Linuxのmktempはテンプレートを必要としませんが、テンプレートが指定されている場合、Xsの数は6でなければなりません。

ご了承ください -tGNU mktemp では非推奨であるため、より将来性のあるコードは

temp_dir="$(mktemp -q -d -t "$(basename "$0").XXXXXX" 2>/dev/null || mktemp -q -d)"
5
go2null