Я предполагаю, что вы можете изменить имя файла, используя прямой доступ к разделу жесткого диска, и где-нибудь вставить символ '/'. Что происходит - это интересный вопрос ... скорее всего, не то, что вам нужно.
hochl
1
Но краткий ответ должен быть: нет, это не то, что когда-либо следовало делать :-)
Симеон Виссер
Считается ли в счетчике ФС косая черта имени файла в записи каталога? Это не рекомендуется; вы никогда не сможете получить доступ к файлу.
Джонатан Леффлер,
35
Это напоминает мне случай, когда мой друг создал файл с именем, *а затем спросил: «Как мне удалить файл?» Я ответил, rmа затем имя файла. Ну, остальное вы знаете.
Дэвид Хеффернан
1
Для новых пользователей Linux, когда вы не уверены в выражении или имени файла, я думаю, что хорошей практикой будет использовать lsсписок файлов, которые вы хотите удалить, а затем изменить lsкоманду на rmпотом.
Dave F
Ответы:
129
Ответ заключается в том, что вы не можете, если в вашей файловой системе нет ошибки. Вот почему:
Существует системный вызов для переименования вашего файла, определенный в fs/namei.ccalled renameat:
Когда вызывается системный вызов, он выполняет поиск пути ( 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 показывает, как все происходит под капотом (сокращено):
Также обратите внимание, что, по крайней мере, e2fsckлюбое имя файла рассматривается как недопустимое имя файла, которое необходимо исправить - см. Источник . Поэтому, если вы каким-то образом получите имя файла с косой чертой, вы можете использовать его fsckдля решения проблемы.
ehabkost 04
4
@ehabkost Любое имя файла? Похоже на ошибку в e2fsck: p
flarn2006 05
36
Вы можете использовать символ Unicode, который отображается как «/» (например, этот, казалось бы, избыточный глиф ), если ваша файловая система поддерживает его.
Да, именно так: только /, то есть 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
Это зависит от того, какую файловую систему вы используете. Из наиболее популярных:
это не зависит только от файловой системы, системные вызовы во всех системах * nix будут анализировать / как компонент дерева каталогов.
Blackle Mori
2
Символ косой черты жестко закодирован в ядре, независимо от файловой системы (попробуйте сделать это grep -r "'/'" *в исходном коде ядра)
Роберт Мартин
20
@tchrist Извините. «Прямая косая черта» - это вполне приемлемый способ обозначения символа косой черты, чтобы полностью прояснить, к какой косой черте относится. Иногда люди путаются: P
Роберт Мартин
2
Ха, но я думаю, что @tchrist тоже прав. Почему "вперед" подразумевает "/", а "назад" означает "\"? Лучшее объяснение, которое у меня есть до сих пор, заключается в том, что если писать пером, начиная с линии, снизу вверх, '/' перемещается вправо или 'вперед', а '\' перемещается 'влево' или 'назад' при чтении / записи слева направо. Мне не очень нравится это объяснение, отчасти потому, что я не всегда пишу своих персонажей снизу вверх. Я думаю, что если начать сверху и спуститься вниз при написании персонажа, то зачастую лучше.
Джесси Коллинз
4
@jwso Это совершенно побочный момент, но это стандартный канонический язык. Косая черта - это не то, что Unicode называет символами, которые выглядят так, он называет их солидусом, но "\" - это обратная косая черта, которая является синонимом обратной косой черты, следовательно, обратной косой черты. Но если требуется выравнивание, линия вперед и назад - это направление, в котором линия наклоняется или должна падать, причем направление зависит от направления письма (слева направо). Он наклоняется или должен упасть <== или назад, если он выглядит как «\», и ==> или вперед, если он выглядит как «/».
Стюарт Р. Джефферис
4
Только с согласованной кодировкой. Например, вы можете договориться, что %будет закодирован как, %%и это %2Fбудет означать /. Все программы, которые обращались к этому файлу, должны понимать кодировку.
Вообще говоря, вообще не стоит пытаться использовать «плохие» символы в имени файла; даже если вы каким-то образом справитесь с этим, это затрудняет дальнейшее использование файла. Разделитель файловой системы совершенно не работает, поэтому вам нужно будет выбрать альтернативный метод.
Рассматривали ли вы URL-кодирование URL-адреса, а затем его использование в качестве имени файла? В результате должно получиться хорошо, как имя файла, и его легко восстановить из закодированной версии.
Другой вариант - создать индекс - создать имя выходного файла, используя любой метод, который вам нравится - последовательно пронумерованные имена, хеши SHA1, что угодно - затем записать файл с сгенерированной парой имя / URL-адрес. Вы можете сохранить это в хеш-коде и использовать его для поиска URL-адресов в имени файла или наоборот с обратной версией хэша, и вы можете записать его и при необходимости перезагрузить позже.
*
а затем спросил: «Как мне удалить файл?» Я ответил,rm
а затем имя файла. Ну, остальное вы знаете.ls
список файлов, которые вы хотите удалить, а затем изменитьls
команду наrm
потом.Ответы:
Ответ заключается в том, что вы не можете, если в вашей файловой системе нет ошибки. Вот почему:
Существует системный вызов для переименования вашего файла, определенный в
fs/namei.c
calledrenameat
:Когда вызывается системный вызов, он выполняет поиск пути (
do_path_lookup
) к имени. Продолжайте отслеживать это, и мы доберемся доlink_path_walk
этого:Этот код применим к любой файловой системе. Что это значит? Это означает, что если вы попытаетесь передать параметр с реальным
'/'
символом в качестве имени файла традиционными средствами, он не сделает то, что вы хотите. Нет возможности убежать от персонажа. Если файловая система "поддерживает" это, это потому, что они:Кроме того, если вы сделали идти и редактировать байт добавить слэш в имя файла, плохое случится. Это потому, что вы никогда не могли ссылаться на этот файл по имени :( поскольку всякий раз, когда вы это делали, Linux предполагал, что вы ссылаетесь на несуществующий каталог. Использование метода 'rm *' также не сработает, поскольку bash просто расширяет его до имени файла. Даже
rm -rf
не сработает, поскольку простой strace показывает, как все происходит под капотом (сокращено):Обратите внимание, что эти вызовы
unlinkat
не будут выполнены, потому что они должны ссылаться на файлы по имени.источник
e2fsck
любое имя файла рассматривается как недопустимое имя файла, которое необходимо исправить - см. Источник . Поэтому, если вы каким-то образом получите имя файла с косой чертой, вы можете использовать егоfsck
для решения проблемы.e2fsck
: pВы можете использовать символ Unicode, который отображается как «/» (например, этот, казалось бы, избыточный глиф ), если ваша файловая система поддерживает его.
источник
SOLIDUS
, запрещено. Есть много других подходящих кандидатов: ⁄ - U + 2044FRACTION SLASH
; ∕ - это U + 2215DIVISION SLASH
; ⧸ представляет собой U + 29F8BIG SOLIDUS
; / - это U + FF0FFULLWIDTH SOLIDUS
, а ╱ - это U + 2571BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT
. Все будет работать отлично!---
. ваш выбор разделителя может использовать другой символ и варьировать количество повторов.Это зависит от того, какую файловую систему вы используете. Из наиболее популярных:
источник
grep -r "'/'" *
в исходном коде ядра)Только с согласованной кодировкой. Например, вы можете договориться, что
%
будет закодирован как,%%
и это%2F
будет означать/
. Все программы, которые обращались к этому файлу, должны понимать кодировку.источник
Короткий ответ: нет, нельзя. Это необходимый запрет из-за того, как определена структура каталогов.
И, как уже упоминалось, вы можете отобразить символ Юникода, который «выглядит» как косая черта, но это все, что вам нужно.
источник
Вообще говоря, вообще не стоит пытаться использовать «плохие» символы в имени файла; даже если вы каким-то образом справитесь с этим, это затрудняет дальнейшее использование файла. Разделитель файловой системы совершенно не работает, поэтому вам нужно будет выбрать альтернативный метод.
Рассматривали ли вы URL-кодирование URL-адреса, а затем его использование в качестве имени файла? В результате должно получиться хорошо, как имя файла, и его легко восстановить из закодированной версии.
Другой вариант - создать индекс - создать имя выходного файла, используя любой метод, который вам нравится - последовательно пронумерованные имена, хеши SHA1, что угодно - затем записать файл с сгенерированной парой имя / URL-адрес. Вы можете сохранить это в хеш-коде и использовать его для поиска URL-адресов в имени файла или наоборот с обратной версией хэша, и вы можете записать его и при необходимости перезагрузить позже.
источник