Como analisar nomes de arquivo corretamente no Bash

Conteúdo

Bash Shell

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 '

Defina um arquivo com um caractere CR no nome do arquivo

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

O problema ao tentar lidar com um nome de arquivo que inclui CR

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 '{}|'

Mostrando como xargs verão o personagem CR como uma nova linha e dividirão os dados sobre ele

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

Todos os tipos de caracteres especiais em nomes de arquivos.

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 Enterokay) 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

A solução: encontrar -print0 e xargs -0

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 – o mesmo personagem – não visível).

Também observamos que há apenas um CR na saída, que combina com o single CR que inserimos no primeiro nome de arquivo, composto por uma seguido por Enterokay seguido por B.

Para terminar, a saída não introduz uma nova linha (que também contém CR) antes de devolver o $ indicador de terminal, já que as correntes eram NULL e não CR finalizado. Pressionamos entrar no $ prompt de terminal para explicar as coisas um pouco.

Então nós adicionamos xargs com ele -0 opções, o que permite xargs para lidar com o NULL terminou a entrada corretamente. Vemos que a entrada foi aprovada e recebida de ls é claro e não há alteração da transformação do texto.

Para terminar, tentamos novamente o nosso rm comando, e desta vez para todos os arquivos, incluindo o original contendo o CR com quem tivemos problemas. a rm funciona muito bem e não há erros ou problemas de análise. Excelente!

Final

Vimos como é essencial, em vários casos, analisar e lidar com nomes de arquivos corretamente no bash. Enquanto aprende a usar find corretamente é um pouco mais desafiador do que apenas usar ls, os benefícios que oferece podem compensar no final. Maior segurança e sem problemas com caracteres especiais.

Se você gostou deste post, você também pode querer ler Como renomear arquivos para nomes de arquivo numéricos no Linux, mostrando um interessante e um tanto complexo find -print0 | xargs -0 demonstração. Desfrutar!

Assine a nossa newsletter

Nós não enviaremos SPAM para você. Nós odiamos isso tanto quanto você.