Quais caracteres precisam ser escapados em arquivos sem aspas?

12

Eu tenho shell / terminal baseado em navegador que executa comandos bash e estou escapando de espaços, mas acontece que os parênteses também precisam ser escapados. Quais outros caracteres precisam ser escapados para nomes de arquivos que não estão entre aspas?

jcubic
fonte
Não está nada claro o que você está tentando fazer. E o que o preenchimento automático tem a ver com alguma coisa?
Michael Vehrs
@MichaelVehrs Tenho comando mv filename filename-foono bash, de quais caracteres preciso escapar, além de espaços e parênteses?
jcubic
@MichaelVehrs removeu a menção de preenchimento automático.
jcubic
Basicamente, todos os metacaracteres do shell, como espaço em branco, globs do shell, eventos do histórico. Por esta razão, você deve citar todo o nome do arquivo, em vez de escapar caracteres individuais: mv "$filename" "$newname".
Michael Vehrs
@ MichaelVehrs Eu sei que a citação resolverá o problema com escape, mas eu preciso usar o nome do arquivo sem aspas. Eu tenho emulador de terminal e deve funcionar quando o usuário não usa aspas.
jcubic

Respostas:

22

A solução simples é colocar uma aspas simples ( ') no início e outra aspas simples no final e substituir todos os 'caracteres dentro do nome do arquivo pela sequência de 4 caracteres '\''. Todos os caracteres perdem seu significado especial dentro de uma sequência de aspas simples, exceto 'ela mesma, que marca o final da sequência. A sequência '\''termina o literal entre aspas simples, segue imediatamente por aspas simples e abre um novo literal entre aspas. Assim, o nome do arquivo

This file's name has some weird characters!
Will you manage to escape them?

pode ser citado da seguinte maneira:

somecommand 'This file'\''s name has some weird characters!
Will you manage to escape them?'

As aspas duplas têm regras de escape mais complexas e não permitem que você inclua um ponto de exclamação !se a substituição do histórico estiver ativada; portanto, não as considerarei mais.

Uma abordagem alternativa é proteger caracteres com barras invertidas. Isso funciona para todos os personagens, exceto novas linhas; para uma nova linha, colocá-la entre aspas simples (ou aspas duplas) é a única solução. Se você deseja minimizar o número de barras invertidas para apresentar o nome entre aspas ao usuário, você pode restringi-lo a locais onde a barra invertida é necessária; no entanto, quanto mais barras invertidas você omitir, maior o risco de esquecer uma que é necessária. Letras, dígitos e caracteres não ASCII estão sempre ok¹. Cite espaços em branco e pontuação sempre que não tiver certeza.

Com um shell típico (ksh, bash ou zsh), é necessário citar os seguintes caracteres em pelo menos algumas circunstâncias.

  • Espaço em branco (espaço, tabulação, nova linha - lembrando que as novas linhas não podem ser citadas com uma barra invertida).
  • ! - expansão da história.
  • " - sintaxe do shell.
  • #- início do comentário quando precedido por espaço em branco; curingas zsh.
  • $ - sintaxe do shell.
  • & - sintaxe do shell.
  • ' - sintaxe do shell.
  • (- mesmo no meio de uma palavra: ksh globs estendidos (também disponível no bash e zsh); curingas zsh.
  • )(ver ()
  • * - curinga sh.
  • , - somente expansão interna da braçadeira.
  • ; - sintaxe do shell.
  • < - sintaxe do shell.
  • = - no zsh, quando está no início de um nome de arquivo (expansão de nome de arquivo com pesquisa PATH).
  • > - sintaxe do shell.
  • ? - curinga sh.
  • [ - curinga sh.
  • \ - sintaxe do shell.
  • ] - você pode deixar isso sem aspas.
  • ^- expansão da história; curinga zsh.
  • ` - sintaxe do shell.
  • { - expansão de cinta.
  • | - sintaxe do shell.
  • } - precisa ser escapado no zsh, outros shells são mais brandos quando não há chave de abertura correspondente.
  • ~- expansão do diretório inicial quando está no início de um nome de arquivo; curinga zsh; sempre seguro quando é o último caractere.

Mais alguns caracteres podem exigir tratamento especial às vezes:

  • -não é especial para o shell, mas quando está no início de um argumento de comando, indica uma opção. Não pode ser protegido com aspas, pois o tratamento especial está no comando, não no shell. Para proteger um nome de arquivo que começa com -, você pode colocá- ./lo antes - dessa forma, ainda é o mesmo arquivo, mas o argumento não começa -mais.
  • .não é especial por si só, mas os arquivos de ponto são excluídos dos *globs por padrão.
  • :não é especial para o shell, mas alguns comandos o analisam especialmente, por exemplo, para indicar um arquivo remoto ( hostname:filename). Consulte a documentação do comando para ver como lidar com nomes de arquivos que contêm dois pontos.

¹ A menos que o usuário tenha configurado caracteres alternativos de expansão do histórico. Algumas conchas permitem isso. Esse é outro motivo para usar aspas simples em vez de barras invertidas.

Gilles 'SO- parar de ser mau'
fonte
Novas linhas, pelo menos LFapenas, podem ser citadas com uma barra invertida em algumas conchas.
iBug
@iBug Não. Em qualquer shell semelhante a sh, a barra invertida + nova linha se expande para uma cadeia vazia, não para uma nova linha.
Gilles 'SO- stop be evil'
Esta é uma boa resposta, obrigado. Existe um link para onde essas informações estão 'oficialmente' disponíveis?
Slashmais 15/08/19
1
@slashmais Que informações? A sintaxe da linguagem shell está "oficialmente" disponível em vários manuais e especificações, mas vai daí para descobrir exatamente quais caracteres precisam ser citados, onde não é completamente simples.
Gilles 'SO- stop be evil'
1
Também encontrei o seguinte: tecmint.com/manage-linux-filenames-with-special-characters - não é tão compacto quanto a sua lista, mas possui muitos exemplos. (by-the-by: "Que informação" não é uma resposta fria quando o assunto aqui diz respeito aos caracteres)
slashmais