Est-il possible d'utiliser «/» dans un nom de fichier?

111

Je sais que ce n'est pas quelque chose qui devrait jamais être fait, mais y a-t-il un moyen d'utiliser le caractère barre oblique qui sépare normalement les répertoires dans un nom de fichier sous Linux?

sous-scan
la source
1
Je suppose que vous pouvez modifier le nom d'un fichier en utilisant un accès direct à votre partition de disque dur et patcher quelque part un caractère «/». Ce qui se passe est une question intéressante ... probablement pas ce que vous voulez.
hochl
1
Mais la réponse courte devrait être: non, ce n'est pas quelque chose qui devrait jamais être fait :-)
Simeon Visser
Est-ce que le piratage d'une barre oblique dans le nom de fichier dans l'entrée de répertoire dans le compte FS? Ce ne serait pas recommandé; vous ne pourrez jamais accéder au fichier.
Jonathan Leffler
35
Cela me rappelle la fois où mon ami a créé un fichier nommé *, puis a demandé: "Comment supprimer un fichier?" J'ai répondu, rmsuivi du nom du fichier. Eh bien, vous connaissez le reste.
David Heffernan
1
Pour les nouveaux utilisateurs de Linux, lorsque vous n'êtes pas sûr d'une expression ou d'un nom de fichier, je pense que c'est une bonne pratique à utiliser lspour répertorier les fichiers que vous souhaitez supprimer, puis pour modifier la lscommande par la rmsuite.
Dave F

Réponses:

129

La réponse est que vous ne pouvez pas, sauf si votre système de fichiers a un bogue. Voici pourquoi:

Il y a un appel système pour renommer votre fichier défini dans fs/namei.cappelé renameat:

SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
                int, newdfd, const char __user *, newname)

Lorsque l'appel système est appelé, il effectue une recherche de chemin ( do_path_lookup) sur le nom. Continuez à tracer cela, et nous arrivons à link_path_walkqui a ceci:

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;
...

Ce code s'applique à n'importe quel système de fichiers. Qu'est-ce que ça veut dire? Cela signifie que si vous essayez de passer un paramètre avec un '/'caractère réel comme nom du fichier en utilisant des moyens traditionnels, il ne fera pas ce que vous voulez. Il n'y a aucun moyen d'échapper au personnage. Si un système de fichiers «prend en charge» cela, c'est parce qu'ils:

  • Utilisez un caractère Unicode ou quelque chose qui ressemble à une barre oblique mais qui ne l'est pas.
  • Ils ont un bug.

De plus, si vous avez fait entrer et modifier les octets pour ajouter un caractère slash dans un nom de fichier, les mauvaises choses se produiraient. C'est parce que vous ne pourriez jamais faire référence à ce fichier par son nom: (puisque chaque fois que vous le faites, Linux supposerait que vous faites référence à un répertoire inexistant. Utiliser la technique 'rm *' ne fonctionnerait pas non plus, puisque bash étend simplement cela au nom de fichier. Cela rm -rfne fonctionnerait même pas, puisqu'un simple strace révèle comment les choses se passent sous le capot (raccourci):

$ 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
...

Notez que ces appels unlinkatéchouent car ils doivent faire référence aux fichiers par leur nom.

Robert Martin
la source
8
Notez également qu'au moins e2fsckconsidère tout nom de fichier comme un nom de fichier illégal qui doit être corrigé - voir la source . Donc, si vous vous retrouvez avec un nom de fichier contenant des barres obliques, vous pouvez l'utiliser fsckpour résoudre le problème.
ehabkost le
4
@ehabkost Un nom de fichier? Sonne comme un bug dans e2fsck: p
flarn2006
36

Vous pouvez utiliser un caractère Unicode qui s'affiche comme "/" (par exemple, ce glyphe apparemment redondant ) en supposant que votre système de fichiers le prend en charge.

Blackle Mori
la source
43
Oui, précisément: seul /, qui vaut U + 002F SOLIDUS, est interdit. Il existe de nombreux autres candidats appropriés: ⁄ vaut U + 2044 FRACTION SLASH; ∕ est U + 2215 DIVISION SLASH; ⧸ est U + 29F8 BIG SOLIDUS; / Est U + FF0F FULLWIDTH SOLIDUSet ╱ est U + 2571 est BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT. Tout fonctionnerait admirablement!
tchrist
2
Mais que se passe-t-il si l'utilisateur utilise ces caractères réels dans ses noms de fichier / répertoire? Nous avons besoin d'une solution d'échappement générique. Dommage que le code normal de Linux n'en supporte aucun, car il correspond littéralement à ASCII 0x2F. ASCII est un grand non-non depuis au moins 20 ans. (Unicode 1.0 date de 1991!)
Evi1M4chine
@tchrist je préfère ne pas dépendre de l'Unicode. donc je préférerais probablement un délimiteur à plusieurs caractères comme ---. votre choix de délimiteur peut utiliser un caractère différent et faire varier le nombre de répétitions.
Trevor Boyd Smith
Pour une liste des remplacements possibles sur de nombreux personnages, qui sont interdits sous différents systèmes de fichiers, jetez un œil à ma réponse: stackoverflow.com/a/61448658/4575793
Cadoiz
9

Cela dépend du système de fichiers que vous utilisez. Parmi les plus populaires:

Nicolas
la source
1
cela ne dépend pas seulement du système de fichiers, les appels système dans tous les systèmes * nix analyseront le / comme un composant de l'arborescence de répertoires.
Blackle Mori
2
Le caractère barre oblique est codé en dur dans le noyau, indépendamment du système de fichiers (essayez de faire grep -r "'/'" *dans votre source de noyau)
Robert Martin
20
@tchrist Excusez-moi. "Barre oblique" est une manière tout à fait acceptable de se référer au caractère barre oblique pour bien préciser à quelle barre oblique on se réfère. Parfois, les gens sont confus: P
Robert Martin
2
Hah, mais @tchrist a aussi un point, je pense. Pourquoi l'avant 'implique' / 'et' arrière 'implique-t-il' \ '? La meilleure explication que j'ai jusqu'ici est que s'il est écrit avec un stylo commençant sur une ligne, de bas en haut, '/' se déplace vers la droite ou 'vers l'avant' et '\' se déplace 'vers la gauche' ou 'vers l'arrière', lors de la lecture / écriture de gauche à droite. Je n'aime pas vraiment cette explication, en partie parce que je n'écris pas toujours mes personnages par le bas et que je monte. Je pense que commencer par le haut et descendre en écrivant un personnage s'écoule souvent mieux.
Jesse W. Collins
4
@jwso C'est totalement un point secondaire, mais c'est un langage canonique standard. Slash n'est pas ce que l'Unicode appelle des symboles qui ressemblent à ceux-ci, il les appelle solidus, mais "\" est un solidus inversé, qui est synonyme de backslash, donc de backslash. Mais si l'on a besoin d'une justification, vers l'arrière et vers l'avant sont la direction dans laquelle la ligne penche ou doit tomber, avec une direction basée sur la direction d'écriture (de gauche à droite). Il penche ou doit tomber <== ou vers l'arrière s'il ressemble à "\", et ==> ou vers l'avant s'il ressemble à "/".
Stuart R. Jefferys
4

Uniquement avec un encodage convenu. Par exemple, vous pourriez convenir que %sera encodé comme %%et cela %2Fsignifiera un fichier /. Tous les logiciels ayant accédé à ce fichier devraient comprendre l'encodage.

David Schwartz
la source
19
"ce que nous appelons une barre oblique sous un autre nom aurait une odeur nauséabonde" - Shakespeare
Robert Martin
1

La réponse courte est: non, vous ne pouvez pas. C'est une interdiction nécessaire en raison de la façon dont la structure des répertoires est définie.

Et, comme mentionné, vous pouvez afficher un caractère Unicode qui "ressemble" à une barre oblique, mais c'est tout ce que vous obtenez.

keyer
la source
1

En général, c'est une mauvaise idée d'essayer d'utiliser des "mauvais" caractères dans un nom de fichier. même si vous le gérez d'une manière ou d'une autre, il a tendance à rendre difficile l'utilisation du fichier plus tard. Le séparateur de système de fichiers ne fonctionnera pas du tout, vous devrez donc choisir une méthode alternative.

Avez-vous envisagé d'encoder l'URL puis de l'utiliser comme nom de fichier? Le résultat devrait être correct en tant que nom de fichier, et il est facile de reconstruire le nom à partir de la version codée.

Une autre option est de créer un index - créer le nom de fichier de sortie en utilisant la méthode que vous voulez - noms numérotés séquentiellement, hachages SHA1, peu importe - puis écrire un fichier avec la paire nom de fichier / URL générée. Vous pouvez l'enregistrer dans un hachage et l'utiliser pour effectuer une recherche d'URL vers le nom de fichier ou vice-versa avec la version inversée du hachage, et vous pouvez l'écrire et le recharger plus tard si nécessaire.

Joe McMahon
la source