As convenções de nomenclatura de arquivos Bash são muito ricas e é fácil criar um script ou linha que analisa nomes de arquivo incorretamente. Aprenda a analisar nomes de arquivos corretamente e, por isso, certifique-se de que seus scripts funcionem conforme o esperado.
O problema de analisar corretamente os nomes dos arquivos no Bash
Se você usa o Bash há um tempo e escreve em sua rica linguagem Bash, você provavelmente já encontrou alguns problemas de análise de nome de arquivo. Vamos dar uma olhada em um exemplo simples do que pode dar errado:
toque em 'a > b '
Aqui, criamos um arquivo que tem um CR
(retorno de carro) entrou pressionando enter após o a
. As convenções de nomenclatura de arquivos Bash são muito ricas, e mesmo que seja de alguma forma legal, podemos usar caracteres especiais como estes em um nome de arquivo, vamos ver como este arquivo se sai quando tentamos realizar algumas ações nele:
ls | xargs rm
Isso não é funcional. xargs
pegará a entrada de ls
(através dele |
pipeline) e passe para rm
, Mas algo deu errado no procedimento!
O que deu errado é que a saída de ls
é interpretado literalmente por xargs
, e o 'entrar’ (CR
– Retorno de carro) dentro do nome do arquivo é visto por xargs
como um personagem final real, não um CR
para ser passado para rm
como deveria ser.
Vamos exemplificar isso de outra maneira:
ls | xargs -I{} eco '{}|'
Está claro.: xargs
você está processando a entrada como duas linhas individuais, divisão do nome do arquivo original em dois. Mesmo que tivéssemos que corrigir problemas espaciais através de uma análise elegante usando sede, logo encontraríamos outros problemas quando começamos a usar outros personagens especiais como espaços., barras traseiras, aspas e mais.
touch 'a b' touch 'a b' touch 'ab' touch 'a"b' touch "a'b" ls
Mesmo que você seja um desenvolvedor bash experiente, você pode ser abalado por ver nomes de arquivos como este, uma vez que seria muito complexo, para as ferramentas bash mais comuns, digitalizar esses arquivos corretamente. Você teria que fazer todo tipo de modificações em cadeia para que isso funcionasse.. Em outras palavras, a menos que você tenha a receita secreta.
Antes de mergulharmos nisso, há mais uma coisa, algo que você deve saber, você pode encontrar ao analisar ls
Produção. Se você usar codificação de cores para listas de diretórios, que é habilitado por padrão no Ubuntu, é fácil executar outro conjunto de ls
problemas de análise.
Eles não estão realmente relacionados a como os arquivos são nomeados, mas sim com a forma como os arquivos são apresentados como saída de ls
. a ls
a saída conterá códigos hexadecimais que representam a cor a ser usada em seu terminal.
Para evitar encontrar estes, Apenas use --color=never
como uma opção para ls
:ls --color=never
.
E hortelã 20 (um ótimo sistema operacional derivado do Ubuntu), este problema parece resolvido, mesmo que seja possível que o problema ainda esteja presente em muitas outras versões do Ubuntu ou anteriores, etc. Eu vi esse problema em meados de agosto 2020 no Ubuntu.
Mesmo se você não usar um código de cores para suas listagens de diretório, seu script provavelmente será executado em outros sistemas que não são de sua propriedade ou gerenciados por você. Em tal caso, você também vai querer usar esta opção para evitar que os usuários dessa máquina tenham o problema descrito.
Voltando à nossa receita secreta, Vamos ver como podemos ter certeza de que não teremos problemas com os caracteres especiais nos nomes dos arquivos Bash. A resposta fornecida evita todo o uso de ls
, que você faria bem em evitar em geral, portanto, os problemas de codificação de cores também não são aplicáveis.
Ainda há momentos em que ls
A análise é rápida e conveniente, mas sempre será complicado e provavelmente 'sujo’ assim que os caracteres especiais forem inseridos, para não mencionar que eles são inseguros (caracteres especiais podem ser usados para introduzir todos os tipos de problemas).
A receita secreta: Rescisão NULL
Os desenvolvedores de ferramentas Bash perceberam esse mesmo problema muitos anos antes e nos forneceram: NULL
terminação!
O que é NULL
perguntas de conclusão? Considere como nos exemplos acima, CR
(o literalmente entrar) foi o personagem final principal.
Também vimos como você pode usar caracteres especiais, como aspas, espaços em branco e barras invertidas nos nomes dos arquivos, embora tenham funções especiais quando se trata de outras ferramentas de modificação e análise de texto Bash, como sed. Agora compare isso com o -0
opção a xargs, a partir de man xargs
:
-0, -nulo Os itens de entrada terminam com um caractere nulo em vez de um espaço em branco, e as aspas e a barra invertida não são especiais (todos os personagens são interpretados literalmente). Desativar string de fim de arquivo, que é tratado como qualquer outro argumento. Útil quando os itens de entrada podem conter espaços em branco, aspas ou barras invertidas. A opção GNU find -print0 produz uma entrada adequada para este modo.
E ele -print0
opção a find
, a partir de man find
:
-fprint0 archivo Certo; imprime o nome completo do arquivo na saída padrão, seguido por um caracter nulo (em vez do caractere de nova linha que usa -print). Isso permite que os programas que processam a saída da pesquisa interpretem corretamente os nomes dos arquivos que contêm novas linhas ou outros tipos de espaço em branco.. Esta opção corresponde à opção -0 de xargs.
a Certo; aqui significa Se a opção for especificada, o seguinte é verdade;. Também interessantes são os dois avisos claros que são dados em outras partes da mesma página do manual:
- Se você estiver canalizando a saída de find para outro programa e houver a menor chance de que os arquivos que você está procurando contenham uma nova linha, então você deve considerar seriamente o uso da opção -print0 em vez de -print. Consulte a seção NOMES DE ARQUIVOS INCOMUNS para obter informações sobre como os caracteres incomuns são tratados em nomes de arquivo..
- Se você estiver usando a pesquisa em um script ou em uma situação onde os arquivos correspondentes podem ter nomes arbitrários, você deve considerar o uso -print0 em vez de -imprimir.
Esses avisos claros nos lembram que analisar nomes de arquivos em bash pode ser, E isso é, um negócio complicado. Apesar disto, com as alternativas certas para find
, a saber -print0
, e xargs
, a saber -0
, todos os nossos caracteres especiais contendo nomes de arquivos podem ser digitalizados corretamente:
ls find . -name 'a*' -print0 find . -nome 'a*' -print0 | xargs -0 ls find . -nome 'a*' -print0 | xargs -0 rm
Primeiro revisamos nossa lista de diretórios. Todos os nossos nomes de arquivos contendo caracteres especiais estão lá. Em seguida, fazemos um simples find ... -print0
para ver a saída. Observamos que as cordas são NULL
finalizado (com ele NULL
o