Até onde eu sei, um nome de arquivo seguro e portátil pode consistir em aA-zZ 0-9 hífen e sublinhado apenas. Ao mesmo tempo, se nos afastarmos das práticas seguras de nomeação de arquivos, podemos usar caracteres como !
?
$
%
"
'
/
e assim por diante.
Minha pergunta é sobre aspas, isto é, "
e '
. Elas não são mais perigosas do que, por exemplo, $
ou /
? Por exemplo, se um nome de arquivo contém espaços e precisamos copiar tal arquivo, colocaríamos seu nome entre aspas:
cp "file with spaces" folder_without_spaces
E por isso eu me questiono: as aspas em um nome de arquivo não podem atrapalhar as aspas no código shell às vezes?
Por exemplo, você tem
aaa aaa ccc.txt
aaa "xxx" ccc.txt
e então você usa
for f in *.txt; do mv "$f" backup_dir; done
e então "Bam!" - algo quebrou. Nada está quebrado, na verdade, neste exemplo em particular (pelo menos no Zsh), mas espero que você tenha entendido o que eu quero dizer.
Não.
for f in *.txt; do mv "$f" backup_dir; done
não quebraria (*) . Direi o mesmo que disse em outro lugar: shells modernos são linguagens de programação, não processadores de macro, ou seja, o shell não se expande$f
ali apenas como texto, para ser processado posteriormente para aspas, mas apenas passa internamente o valor como está. Isso é semelhante a algo comoprint(foo)
em Python ser seguro mesmo sefoo
for uma string que contémsys.exit(1)
.Há o fato de que em shells do tipo POSIX a divisão de campos feita em um campo sem aspas
$var
resulta em algo que, para valores simples, se parece com o que você obtém ao colar o valor bruto na linha de comando, mas essa é uma função separada e também não processa aspas do resultado da expansão.A divisão de campos só funciona em espaços em branco (ou o que
IFS
estiver definido), por exemplo,var='"foo bar"'; mv $var /tmp
passamv
os três argumentos,"foo
,bar"
,/tmp
, dividindo no espaço e manipulando as aspas como apenas caracteres regulares. Não é nem um pouco a mesma coisa quemv "foo bar" /tmp
.Expansões sem aspas também passam pelo processo de englobamento de nomes de arquivo, então, por exemplo
?
, or*
(and[...]
) pode causar problemas aqui.Ver:
Claro que o zsh quebra a compatibilidade POSIX aqui, e não faz divisão de campo e globbing para expansões de variáveis. Então
mv $f backup_dir
também deve ser seguro (*) no zsh.O asterisco ali é que se seu diretório contiver nomes de arquivo que começam com um hífen,
mv
ele tentaria analisá-los como opções. Não há nada que o shell quoteing possa fazer sobre isso, já que o programa apenas obtém os argumentos da linha de comando como strings, ele não sabe de onde eles vieram.(Por exemplo, um arquivo chamado
-v.txt
não seria movido, ele seria considerado a-v
opção para o modo detalhado, e a-.
opção inválida produziria um erro. O comando inteiro também não teria o nome do arquivo de destino.)A solução para isso é sempre começar os nomes de caminho relativos com
./
, ou separar as opções de linha de comando dos nomes de arquivo com--
. Ou ambos, para fins de exemplo: