Можно ли использовать «/» в имени файла?


111

Я знаю, что этого никогда не следует делать, но есть ли способ использовать косую черту, которая обычно разделяет каталоги в имени файла в Linux?


1
Я предполагаю, что вы можете изменить имя файла, используя прямой доступ к разделу жесткого диска, и где-нибудь вставить символ '/'. Что происходит - это интересный вопрос ... скорее всего, не то, что вам нужно.
hochl

1
Но краткий ответ должен быть: нет, это не то, что когда-либо следовало делать :-)
Симеон Виссер

Считается ли в счетчике ФС косая черта имени файла в записи каталога? Это не рекомендуется; вы никогда не сможете получить доступ к файлу.
Джонатан Леффлер,

35
Это напоминает мне случай, когда мой друг создал файл с именем, *а затем спросил: «Как мне удалить файл?» Я ответил, rmа затем имя файла. Ну, остальное вы знаете.
Дэвид Хеффернан

1
Для новых пользователей Linux, когда вы не уверены в выражении или имени файла, я думаю, что хорошей практикой будет использовать lsсписок файлов, которые вы хотите удалить, а затем изменить lsкоманду на rmпотом.
Dave F

Ответы:


129

Ответ заключается в том, что вы не можете, если в вашей файловой системе нет ошибки. Вот почему:

Существует системный вызов для переименования вашего файла, определенный в fs/namei.ccalled 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;
...

Этот код применим к любой файловой системе. Что это значит? Это означает, что если вы попытаетесь передать параметр с реальным '/'символом в качестве имени файла традиционными средствами, он не сделает то, что вы хотите. Нет возможности убежать от персонажа. Если файловая система "поддерживает" это, это потому, что они:

  • Используйте символ Юникода или что - то , что выглядит нравится слэш , но это не так .
  • У них есть ошибка.

Кроме того, если вы сделали идти и редактировать байт добавить слэш в имя файла, плохое случится. Это потому, что вы никогда не могли ссылаться на этот файл по имени :( поскольку всякий раз, когда вы это делали, 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не будут выполнены, потому что они должны ссылаться на файлы по имени.


8
Также обратите внимание, что, по крайней мере, e2fsckлюбое имя файла рассматривается как недопустимое имя файла, которое необходимо исправить - см. Источник . Поэтому, если вы каким-то образом получите имя файла с косой чертой, вы можете использовать его fsckдля решения проблемы.
ehabkost 04

4
@ehabkost Любое имя файла? Похоже на ошибку в e2fsck: p
flarn2006 05

36

Вы можете использовать символ Unicode, который отображается как «/» (например, этот, казалось бы, избыточный глиф ), если ваша файловая система поддерживает его.


43
Да, именно так: только /, то есть U + 002F SOLIDUS, запрещено. Есть много других подходящих кандидатов: ⁄ - U + 2044 FRACTION SLASH; ∕ - это U + 2215 DIVISION SLASH; ⧸ представляет собой U + 29F8 BIG SOLIDUS; / - это U + FF0F FULLWIDTH SOLIDUS, а ╱ - это U + 2571 BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT. Все будет работать отлично!
tchrist

2
Но что тогда, если пользователь использует эти фактические символы в своих именах файлов / каталогов? Нам нужно универсальное решение для экранирования. Жаль, что нормальный код Linux не поддерживает ни одного, поскольку он буквально соответствует ASCII 0x2F. ASCII - это большое запрещение уже как минимум 20 лет. (Unicode 1.0 с 1991 года!)
Evi1M4chine

@tchrist Я предпочитаю не зависеть от юникода. поэтому я, вероятно, предпочел бы многосимвольный разделитель, например ---. ваш выбор разделителя может использовать другой символ и варьировать количество повторов.
Тревор Бойд Смит

Список возможных замен многочисленных символов, которые запрещены в разных файловых системах, можно найти в моем ответе: stackoverflow.com/a/61448658/4575793
Cadoiz

9

Это зависит от того, какую файловую систему вы используете. Из наиболее популярных:


1
это не зависит только от файловой системы, системные вызовы во всех системах * nix будут анализировать / как компонент дерева каталогов.
Blackle Mori

2
Символ косой черты жестко закодирован в ядре, независимо от файловой системы (попробуйте сделать это grep -r "'/'" *в исходном коде ядра)
Роберт Мартин

20
@tchrist Извините. «Прямая косая черта» - это вполне приемлемый способ обозначения символа косой черты, чтобы полностью прояснить, к какой косой черте относится. Иногда люди путаются: P
Роберт Мартин

2
Ха, но я думаю, что @tchrist тоже прав. Почему "вперед" подразумевает "/", а "назад" означает "\"? Лучшее объяснение, которое у меня есть до сих пор, заключается в том, что если писать пером, начиная с линии, снизу вверх, '/' перемещается вправо или 'вперед', а '\' перемещается 'влево' или 'назад' при чтении / записи слева направо. Мне не очень нравится это объяснение, отчасти потому, что я не всегда пишу своих персонажей снизу вверх. Я думаю, что если начать сверху и спуститься вниз при написании персонажа, то зачастую лучше.
Джесси Коллинз

4
@jwso Это совершенно побочный момент, но это стандартный канонический язык. Косая черта - это не то, что Unicode называет символами, которые выглядят так, он называет их солидусом, но "\" - это обратная косая черта, которая является синонимом обратной косой черты, следовательно, обратной косой черты. Но если требуется выравнивание, линия вперед и назад - это направление, в котором линия наклоняется или должна падать, причем направление зависит от направления письма (слева направо). Он наклоняется или должен упасть <== или назад, если он выглядит как «\», и ​​==> или вперед, если он выглядит как «/».
Стюарт Р. Джефферис

4

Только с согласованной кодировкой. Например, вы можете договориться, что %будет закодирован как, %%и это %2Fбудет означать /. Все программы, которые обращались к этому файлу, должны понимать кодировку.


19
«то, что мы называем косой чертой под любым другим именем, будет пахнуть мерзостью» - Шекспир
Роберт Мартин

1

Короткий ответ: нет, нельзя. Это необходимый запрет из-за того, как определена структура каталогов.

И, как уже упоминалось, вы можете отобразить символ Юникода, который «выглядит» как косая черта, но это все, что вам нужно.


1

Вообще говоря, вообще не стоит пытаться использовать «плохие» символы в имени файла; даже если вы каким-то образом справитесь с этим, это затрудняет дальнейшее использование файла. Разделитель файловой системы совершенно не работает, поэтому вам нужно будет выбрать альтернативный метод.

Рассматривали ли вы URL-кодирование URL-адреса, а затем его использование в качестве имени файла? В результате должно получиться хорошо, как имя файла, и его легко восстановить из закодированной версии.

Другой вариант - создать индекс - создать имя выходного файла, используя любой метод, который вам нравится - последовательно пронумерованные имена, хеши SHA1, что угодно - затем записать файл с сгенерированной парой имя / URL-адрес. Вы можете сохранить это в хеш-коде и использовать его для поиска URL-адресов в имени файла или наоборот с обратной версией хэша, и вы можете записать его и при необходимости перезагрузить позже.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.