存在しないファイルはありますか?

存在しないファイルはありますか?

(空のソース/シンクファイルパス)行に沿って、/dev/null少なくともLinuxでは有効なファイルを指さないパスはありますか?これは主に私が作成しているいくつかのスクリプトをテストするためのものであり、スクリプトに属していないファイルが存在する場合は削除または移動したくありません。

答え1

あるいは、スクリプトが一時ディレクトリを作成し、その中でファイル名を見つけることをお勧めします。これにより、ファイルが存在しないと100%確実になり、すべての権限を持って直接簡単に整理できます。それは次のとおりです。

dir=$(mktemp -d)
if [ -e "$dir"/somefile ]; then
    echo "Something is seriously wrong here, '$dir/somefile' exists!"
fi
rmdir "$dir"

任意の言語で同等のコードを書くことができ、ほとんどの(すべて?)高度な言語には、一時ディレクトリの作成と削除を処理する専用のツールがあります。これは、存在してはならないファイル名を推測するよりも安全できれいなアプローチのようです。

答え2

/dev/null/foo/dev/nullディレクトリでなければ存在できません。

POSIXの要件/dev/null「空のデータソースと無限のデータシンク」になります。これらの特徴を持つディレクトリを持つことが完全に不可能かどうかはわかりません。それでも私は/dev/nullそれが* nixのディレクトリではないと仮定するのは安全だと思います。

開こうとすると(該当するファイルやディレクトリはありません)、代わりに(ディレクトリではありません)を/dev/null/foo受け取ります。これはテスト目的に応じて許可される場合もあれば許可されていない場合もあります。ENOTDIRENOENT

答え3

暗号化ハンドブックからリーフを取り出すと、十分に大きなランダムな文字列を生成すると、ヒットの可能性がわずかに少ない確率で特定のシステムにのみ存在します。

たとえば、作業ファイルが存在しなければなら/dev/urandomないと仮定すると、次のようにf128ビット乱数に基づいて有効なファイル名が生成されます。

f=/$(head -c 16 /dev/urandom |base64 |tr / ,)

出力は次のとおりです/B90sYd,aNrcw7d7Itcb8fQ==。 (先行スラッシュは固定されており、意図的に絶対パスで作成されています。末尾のスラッシュも==固定されており、Base64パディングのため無視できます。)

1組/秒の速度でランダムなファイル名を生成するシステムは、スクリプトで生成されたファイル名を生成するのに数兆年かかります。衝突だけでは十分ではないので、誕生日攻撃は適用されません。これは基本的に128ビット対称鍵を無差別復号化するのと同じです。

たとえば、次を参照してください。 AES-128 鍵を無差別に代入するのにどれくらい時間がかかりますか?

これは有効な文字列が必要であることに注意してください。誰かがそれをBase64でエンコードするときに、文字列を生成する既知の文字列/dev/urandom(3バイトなど)を含む静的ファイルに置き換えると機能しません。エドコンテキスト。さらに、たとえば、システムのRNGを初期化するための実用的な手段がない組み込みシステムは、問題に直面する可能性があります。この場合は使用しないでください。\x86\x89\x9ehomechroot/dev/urandomこの場合、暗号鍵を生成しないでください。


あるいは、空の文字列を使用することもできます。少なくともLinuxでは、ファイル名として使用しようとするとエラーが発生します。

$ cat ""
cat: '': No such file or directory
$ touch ""
touch: cannot touch '': No such file or directory

(しかし、エラー(ENOENT)は少し面白いです。名前が無効であると思うかもしれません。存在しない.)

これを変数に入れたら、拡張時に引用符を覚えておく必要があります!たとえば、f=; cat $f標準入力から読みます。

$ f=
$ cat "$f"
cat: '': No such file or directory
$ touch "$f"
touch: cannot touch '': No such file or directory

ただし、cd ""シェルでこれを行うと、現在のディレクトリにのみ変更されます。POSIX とそれ"[与えられたパス]が空の文字列の場合、結果は指定されません。"。私が試したすべてのシェルはcallから現在のパスを明示的に使用しますchdir()。たとえば、次のようになります。

/tmp$ strace -etrace=chdir zsh -c 'cd ""'
chdir("/tmp")                           = 0
+++ exited with 0 +++
/tmp$

私の考えは以前(現在)に基づいています。削除済み)答え。これはシステムによって異なる場合もあれば、異なる場合もあります。 Linuxでのみ試しました。警告事項


[ -f ... ]また、コメントで述べたように、どのようなエラーが発生するのか気にしない場合や、シェルやシェルから通知されないものを使用している場合は、[ -e ... ]非常に長いファイル名を作成できます。

ほぼすべてのファイルシステムで、単一ファイルの最大長は255文字以下です(参照:ファイルシステムの比較ウィキペディアから)。フルパスは長いかもしれませんが、256バイトの単一ファイル名は不可能で、次のものを提供しますENAMETOOLONG

$ f=$(printf %256s x | tr ' ' x)
$ touch "$f"
touch: cannot touch 'xxx...xxx': File name too long

しかし、if [ -e "$f" ]; then ...私が試したすべてのシェルにはエラーがなく、テストも失敗しました。

(これPOSIXの定義これが-e「false if」と言うパス名解決できません」というメッセージが表示されますが、診断について明示的に言及しません。

(Wikipediaの表には、ファイルあたりの長さが長い2つのLinuxファイルシステムが記載されていますが、現在広く使用されているかどうかは疑わしく、Linuxは一般的にファイルシステムに関係なく255バイトの制限があることを知っています。)

答え4

テデン素晴らしい答えがすでに提供されています。使用mktemp -d。この記事では、問題をより基本的な方法で調べて説明します。なぜ通常、このコマンドは最良の答えです。

いいえ言葉のない決して存在しない道。しかし、テストスクリプトに関するあなたの文章によると、次のように聞こえます。変えるスクリプトがパスを独自に生成できる限り、パスも同様に良いです。

これらのパスを生成する唯一の方法は、生成されたパスが存在しなくなるまでパス生成を維持することです。残念ながら、これは次のような結果につながる可能性があります。競争条件:その他プログラムファイルを生成できます後ろに存在することを確認するが、今後存在しないファイルに依存する操作を実行します。

この競合状態を回避する最善の方法は、他のプログラムが避けるべきパスを使用することです。/tmp例えば、残念ながら、/tmp世界はしばしば書き込み可能なので、今では大きな問題があります。ユーザーファイルが生成されることがあります。

あなたが本当に望むのは、他のプログラムが避けるべき一時ディレクトリです。そして他のユーザーはアクセスできません。そのディレクトリの下のすべてのパスを使用できるように、ディレクトリが空の場合は良いでしょう。

mktemp -d独自の競争条件から自分自身を保護しながら、前の段落のすべての基準を満たすディレクトリを作成します。完了したら、rmdir次のコマンドを使用してディレクトリを削除できます。

dir="$(mktemp -d)"
# Use "$dir"/foo as a nonexistent path.
rmdir "$dir"

関連情報