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
chamado renameat
:
SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
int, newdfd, const char __user *, newname)
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_walk
qual 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 -rf
não funcionaria, já que um simples traço revela como as coisas acontecem sob o capô (abreviado):
$ 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
...
Observe que essas chamadas para unlinkat
falhariam porque precisam se referir aos arquivos pelo nome.