これは決してすべきことではないことはわかっていますが、Linux で通常ファイル名内のディレクトリを区切るスラッシュ文字を使用する方法はありますか?
8 に答える
答えは、ファイルシステムにバグがない限り、できないということです。理由は次のとおりです。
fs/namei.c
呼び出されたファイルの名前を変更するためのシステムコールが定義されていますrenameat
。
SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
int, newdfd, const char __user *, newname)
システム コールが呼び出されるとdo_path_lookup
、名前に対してパス ルックアップ ( ) が実行されます。これを追跡し続けると、次のlink_path_walk
ものが得られます。
static int link_path_walk(const char *name, struct nameidata *nd)
{
struct path next;
int err;
unsigned int lookup_flags = nd->flags;
while (*name=='/')
name++;
if (!*name)
return 0;
...
このコードは、すべてのファイル システムに適用されます。これはどういう意味ですか?これは、従来の方法を使用してファイル名として実際の文字を使用してパラメーターを渡そうとすると、意図したとおりに動作'/'
しないことを意味します。キャラクターから逃れる方法はありません。ファイルシステムがこれを「サポート」している場合、それは次のいずれかが原因です。
- Unicode 文字またはスラッシュのように見えるがそうでないものを使用します。
- 彼らにはバグがあります。
さらに、バイトを編集してファイル名にスラッシュ文字を追加すると、悪いことが起こります。これは、このファイルを名前で参照することは決してできないためです:(いつでも、Linuxは存在しないディレクトリを参照していると想定するためです。「rm *」手法を使用しても機能しません.bashは単純にそれをファイル名に展開するため.rm -rf
単純な strace がフードの下で物事がどのように進行しているかを明らかにするため、機能しません (短縮) :
$ ls testdir
myfile2 out
$ strace -vf rm -rf testdir
...
unlinkat(3, "myfile2", 0) = 0
unlinkat(3, "out", 0) = 0
fcntl(3, F_GETFD) = 0x1 (flags FD_CLOEXEC)
close(3) = 0
unlinkat(AT_FDCWD, "testdir", AT_REMOVEDIR) = 0
...
ファイルを名前で参照する必要があるため、これらの呼び出しunlinkat
は失敗することに注意してください。
ファイルシステムがサポートしていると仮定すると、「/」として表示される Unicode 文字 (たとえば、この一見冗長な glyph ) を使用できます。
合意されたエンコーディングのみ。たとえば、 がとして%
エンコードされ%%
、. このファイルにアクセスするすべてのソフトウェアは、エンコーディングを理解する必要があります。%2F
/
一般に、ファイル名に「悪い」文字を使用しようとするのは悪い考えです。なんとか管理できたとしても、あとでファイルが使いづらくなってしまいがちです。ファイルシステムの区切りは完全に機能しないため、別の方法を選択する必要があります。
URL を URL エンコードし、それをファイル名として使用することを検討しましたか? 結果はファイル名として問題なく、エンコードされたバージョンから名前を再構築するのは簡単です。
もう 1 つのオプションは、インデックスを作成することです。好きな方法で出力ファイル名を作成し、連番の名前、SHA1 ハッシュなどを使用して、生成されたファイル名/URL ペアでファイルを書き込みます。それをハッシュに保存し、それを使用して URL からファイル名へのルックアップを実行したり、逆バージョンのハッシュを使用してその逆を実行したり、必要に応じて書き出して後で再ロードしたりできます。
簡単に言えば、いいえ、できません。ディレクトリ構造がどのように定義されているかにより、これは必要な禁止事項です。
そして、前述のように、スラッシュに「似ている」Unicode 文字を表示することはできますが、それは可能な限りです。