私はこれがこれまでに行われるべきではないことを知っていますが、Linuxのファイル名内のディレクトリを通常区切るスラッシュ文字を使用する方法はありますか?
答えは、ファイルシステムにバグがない限りできないということです。その理由は次のとおりです。
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;
...
このコードは、すべてのファイルシステムに適用されます。これはどういう意味ですか?つまり、従来の方法を使用して、ファイル名として実際の'/'
文字を使用してパラメーターを渡そうとすると、望みどおりの結果が得られません。キャラクターをエスケープする方法はありません。ファイルシステムがこれを「サポート」しているのは、次のいずれかの理由によるものです。
さらに、didに移動してバイトを編集し、ファイル名にスラッシュ文字を追加すると、悪いことが起こります。これは、名前でこのファイルを参照することができないためです: 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文字を使用できます(たとえば この一見冗長なグリフ )。
合意されたエンコードのみ。たとえば、%
は%%
としてエンコードされ、%2F
は/
を意味することに同意できます。このファイルにアクセスするすべてのソフトウェアは、エンコーディングを理解する必要があります。
簡単な答えは:いいえ、できません。ディレクトリ構造がどのように定義されているかにより、これは必要な禁止事項です。
そして、前述のように、スラッシュのように見えるユニコード文字を表示できますが、それはあなたが得る限りです。
一般に、ファイル名に「悪い」文字を使用しようとするのは悪い考えです。どうにかしてそれを管理しても、後でファイルを使用するのが難しくなる傾向があります。ファイルシステムのセパレータは完全に機能しないため、別の方法を選択する必要があります。
URLをURLエンコードして、それをファイル名として使用することを検討しましたか?結果はファイル名として問題なく、エンコードされたバージョンから名前を簡単に再構築できます。
別のオプションは、インデックスを作成することです-好きな方法を使用して出力ファイル名を作成します-連番の名前、SHA1ハッシュ、その他-生成されたファイル名/ URLペアでファイルを書き込みます。それをハッシュに保存し、それを使用してURLからファイル名へのルックアップ、またはその逆のハッシュを使用し、必要に応じて後で書き直してリロードすることができます。