Eu sei que isso não é algo que deveria ser feito, mas existe uma maneira de usar o caractere de barra que normalmente separa os diretórios dentro de um nome de arquivo no Linux?
Eu acho que você pode modificar o nome de um arquivo usando o acesso direto à partição do seu disco rígido e patch em um caractere '/' em algum lugar. O que acontece é uma questão interessante ... provavelmente não é o que você quer.
hochl
1
Mas a resposta curta deve ser: não, isso não é algo que deveria ser feito :-)
Simeon Visser
Hackear uma barra no nome do arquivo na entrada do diretório no FS conta? Não seria recomendado; você não será capaz de acessar o arquivo, nunca.
Jonathan Leffler
35
Isso me lembra de quando meu amigo criou um arquivo chamado *e perguntou: "Como faço para remover um arquivo?" Eu respondi, rmseguido pelo nome do arquivo. Bem, você sabe o restante.
David Heffernan
1
Para novos usuários do Linux, quando você não tem certeza sobre uma expressão ou nome de arquivo, acho que é uma boa prática usar lspara listar os arquivos que você deseja remover e, em seguida, alterar o lscomando para rmdepois.
Dave F
Respostas:
129
A resposta é que você não pode, a menos que seu sistema de arquivos tenha um bug. Aqui está o porquê:
Há uma chamada de sistema para renomear seu arquivo definido em fs/namei.cchamado renameat:
Quando a chamada do sistema é invocada, ela faz uma pesquisa de caminho ( do_path_lookup) no nome. Continue rastreando isso, e chegaremos a link_path_walkqual tem o seguinte:
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;
...
Este código se aplica a qualquer sistema de arquivos. O que isso significa? Isso significa que se você tentar passar um parâmetro com um '/'caractere real como o nome do arquivo usando os meios tradicionais, ele não fará o que você deseja. Não há como escapar do personagem. Se um sistema de arquivos "suporta" isso, é porque:
Use um caractere Unicode ou algo que se pareça com uma barra, mas não é.
Eles têm um bug.
Além disso, se você fez entrar e editar os bytes para adicionar um caractere de barra em um nome de arquivo, coisas ruins aconteceriam. Isso porque você nunca poderia se referir a este arquivo pelo nome :( já que sempre que o fizesse, o Linux assumiria que você estava se referindo a um diretório inexistente. Usar a técnica 'rm *' também não funcionaria, pois o bash simplesmente a expande para o nome do arquivo. Mesmo rm -rfnão funcionaria, já que um simples traço revela como as coisas acontecem sob o capô (abreviado):
Além disso, observe que pelo menos e2fsckconsidera qualquer nome de arquivo como um nome de arquivo ilegal que deve ser corrigido - consulte a fonte . Portanto, se, de alguma forma, acabar com um nome de arquivo com barras, você pode usar fsckpara corrigir o problema.
ehabkost
4
@ehabkost Qualquer nome de arquivo? Parece um bug em e2fsck: p
flarn2006
36
Você pode usar um caractere Unicode exibido como "/" (por exemplo, este glifo aparentemente redundante ), supondo que seu sistema de arquivos o suporte.
Sim, precisamente: apenas /, que é U + 002F SOLIDUS, é proibido. Existem muitos outros candidatos adequados: ⁄ é U + 2044 FRACTION SLASH; ∕ é U + 2215 DIVISION SLASH; ⧸ é U + 29F8 BIG SOLIDUS; / É U + FF0F FULLWIDTH SOLIDUSe ╱ é U + 2571 is BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT. Tudo funcionaria admiravelmente!
tchrist
2
Mas e se o usuário usar esses caracteres reais em seus nomes de arquivo / diretório? Precisamos de uma solução de escape genérica. Pena que o código normal do Linux não suporta nenhum, já que ele corresponde literalmente ao ASCII 0x2F. ASCII é uma grande proibição desde pelo menos 20 anos. (Unicode 1.0 é de 1991!)
Evi1M4chine
@tchrist eu prefiro não depender do Unicode. então eu provavelmente preferiria um delimitador de vários caracteres como ---. sua escolha de delimitador pode usar um caractere diferente e variar o número de repetições.
Trevor Boyd Smith
Para uma lista de possíveis substituições em vários caracteres, que são proibidas em diferentes sistemas de arquivos, dê uma olhada em minha resposta: stackoverflow.com/a/61448658/4575793
Cadoiz
9
Depende de qual sistema de arquivos você está usando. De alguns dos mais populares:
não depende apenas do sistema de arquivos, chamadas de sistema em todos os sistemas * nix analisarão o / como um componente da árvore de diretórios.
Blackle Mori
2
O caractere de barra é embutido no kernel, independente do sistema de arquivos (tente fazer grep -r "'/'" *na fonte do kernel)
Robert Martin
20
@tchrist Com licença. "Barra para frente" é uma forma completamente aceitável de se referir ao caractere de barra para deixar bem claro a qual barra se refere. Às vezes as pessoas ficam confusas: P
Robert Martin
2
Hah, mas @tchrist também tem razão, eu acho. Por que avançar 'implica' / 'e' voltar 'implica' \ '? A melhor explicação que tenho até agora é que se escrito com uma caneta começando em uma linha, de baixo para cima, '/' move-se para a direita ou 'para frente' e '\' move-se para 'esquerda' ou 'para trás', ao ler / escrever da esquerda para a direita. Eu realmente não gosto dessa explicação, em parte porque nem sempre escrevo meus personagens de baixo para cima e subo. Acho que começar de cima e descer enquanto escrevo um personagem geralmente flui melhor.
Jesse W. Collins,
4
@jwso Este é um ponto totalmente lateral, mas é uma linguagem canônica padrão. Slash não é o que o Unicode chama de símbolos que se parecem com esses, ele os chama de solidus, mas "\" é um solidus reverso, que é sinônimo de reverso, portanto, barra invertida. Mas se for preciso uma justificativa, para frente e para trás são a direção em que a linha se inclina ou deve cair, com direção baseada na direção da escrita (da esquerda para a direita). Ele se inclina ou deve cair <== ou para trás se for semelhante a "\" e ==> ou para frente se for semelhante a "/".
Stuart R. Jefferys
4
Apenas com uma codificação acordada. Por exemplo, você pode concordar que %será codificado como %%e que %2Fsignificará a /. Todo software que acessasse este arquivo teria que entender a codificação.
Em geral, é uma má ideia tentar usar caracteres "ruins" em um nome de arquivo; mesmo que você o gerencie de alguma forma, ele tende a dificultar o uso do arquivo posteriormente. O separador do sistema de arquivos simplesmente não vai funcionar, então você vai precisar escolher um método alternativo.
Você já pensou em codificar o URL e usá-lo como nome de arquivo? O resultado deve ser bom como um nome de arquivo e é fácil reconstruir o nome da versão codificada.
Outra opção é criar um índice - criar o nome do arquivo de saída usando o método que você quiser - nomes numerados sequencialmente, hashes SHA1, qualquer que seja - e então escrever um arquivo com o par nome de arquivo / URL gerado. Você pode salvá-lo em um hash e usá-lo para fazer uma pesquisa de URL para nome de arquivo ou vice-versa com a versão reversa do hash, e pode escrever e recarregar mais tarde, se necessário.
*
e perguntou: "Como faço para remover um arquivo?" Eu respondi,rm
seguido pelo nome do arquivo. Bem, você sabe o restante.ls
para listar os arquivos que você deseja remover e, em seguida, alterar ols
comando pararm
depois.Respostas:
A resposta é que você não pode, a menos que seu sistema de arquivos tenha um bug. Aqui está o porquê:
Há uma chamada de sistema para renomear seu arquivo definido em
fs/namei.c
chamadorenameat
:Quando a chamada do sistema é invocada, ela faz uma pesquisa de caminho (
do_path_lookup
) no nome. Continue rastreando isso, e chegaremos alink_path_walk
qual tem o seguinte:Este código se aplica a qualquer sistema de arquivos. O que isso significa? Isso significa que se você tentar passar um parâmetro com um
'/'
caractere real como o nome do arquivo usando os meios tradicionais, ele não fará o que você deseja. Não há como escapar do personagem. Se um sistema de arquivos "suporta" isso, é porque:Além disso, se você fez entrar e editar os bytes para adicionar um caractere de barra em um nome de arquivo, coisas ruins aconteceriam. Isso porque você nunca poderia se referir a este arquivo pelo nome :( já que sempre que o fizesse, o Linux assumiria que você estava se referindo a um diretório inexistente. Usar a técnica 'rm *' também não funcionaria, pois o bash simplesmente a expande para o nome do arquivo. Mesmo
rm -rf
não funcionaria, já que um simples traço revela como as coisas acontecem sob o capô (abreviado):Observe que essas chamadas para
unlinkat
falhariam porque precisam se referir aos arquivos pelo nome.fonte
e2fsck
considera qualquer nome de arquivo como um nome de arquivo ilegal que deve ser corrigido - consulte a fonte . Portanto, se, de alguma forma, acabar com um nome de arquivo com barras, você pode usarfsck
para corrigir o problema.e2fsck
: pVocê pode usar um caractere Unicode exibido como "/" (por exemplo, este glifo aparentemente redundante ), supondo que seu sistema de arquivos o suporte.
fonte
SOLIDUS
, é proibido. Existem muitos outros candidatos adequados: ⁄ é U + 2044FRACTION SLASH
; ∕ é U + 2215DIVISION SLASH
; ⧸ é U + 29F8BIG SOLIDUS
; / É U + FF0FFULLWIDTH SOLIDUS
e ╱ é U + 2571 isBOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT
. Tudo funcionaria admiravelmente!---
. sua escolha de delimitador pode usar um caractere diferente e variar o número de repetições.Depende de qual sistema de arquivos você está usando. De alguns dos mais populares:
fonte
grep -r "'/'" *
na fonte do kernel)Apenas com uma codificação acordada. Por exemplo, você pode concordar que
%
será codificado como%%
e que%2F
significará a/
. Todo software que acessasse este arquivo teria que entender a codificação.fonte
A resposta curta é: Não, você não pode. É uma proibição necessária devido à forma como a estrutura do diretório é definida.
E, como mencionado, você pode exibir um caractere Unicode que "se parece" com uma barra, mas isso é o máximo que você consegue.
fonte
Em geral, é uma má ideia tentar usar caracteres "ruins" em um nome de arquivo; mesmo que você o gerencie de alguma forma, ele tende a dificultar o uso do arquivo posteriormente. O separador do sistema de arquivos simplesmente não vai funcionar, então você vai precisar escolher um método alternativo.
Você já pensou em codificar o URL e usá-lo como nome de arquivo? O resultado deve ser bom como um nome de arquivo e é fácil reconstruir o nome da versão codificada.
Outra opção é criar um índice - criar o nome do arquivo de saída usando o método que você quiser - nomes numerados sequencialmente, hashes SHA1, qualquer que seja - e então escrever um arquivo com o par nome de arquivo / URL gerado. Você pode salvá-lo em um hash e usá-lo para fazer uma pesquisa de URL para nome de arquivo ou vice-versa com a versão reversa do hash, e pode escrever e recarregar mais tarde, se necessário.
fonte