git-bash como lidar com espaços em nomes de arquivos


1

Eu escrevi o seguinte script para ser executado sob o git-bash no Windows 7:

#!/usr/bin/env sh
for logfile in `find -name "*.log" -o -name "*.err" -o -name "*.out"`
do
    echo $logfile
    grep "api/" "$logfile"
done

O problema é que o grep engasga quando um nome de arquivo tem um espaço nele. Eu pensei que as aspas duplas deveriam cuidar disso, mas não é cooperativo.

Idéias?

Alternativamente, você pode dizer o que estou tentando fazer. Qualquer outra sugestão seria bem vinda.

Respostas:


3

Solução 1

A solução mais próxima é usar find com -print0 e leia a saída com while read …:

find -name "*.log" -o -name "*.err" -o -name "*.out" -type f -print0 | while IFS= read -r -d '' logfile; do
    ...

Continue usando "$logfile" com aspas, como você sempre deve ao usar variáveis.

Solução 2

Outra solução seria não usar find em tudo e apenas deixe grep executar em vários arquivos:

shopt -s nullglob
shopt -s globstar
grep "api/" **/*.log **/*.err **/*.out

Aqui, globstar permite a correspondência recursiva de diretórios com **. Você deve definir nullglob para evitar erros se uma dessas extensões de arquivo não existir.

Isso só funciona para um conjunto limitado de arquivos, pois você pode atingir o tamanho máximo dos argumentos da linha de comando.

Por que o erro acontece?

Você nunca deve correr for na saída de find (ou ls, ou qualquer outra função que produza nomes de arquivos com espaço em branco). Ler Este artigo para mais informações sobre por que isso é um problema e o que pode ser feito para resolvê-lo.

Em suma, o Bash divide os argumentos por espaço em branco. Imagine que você tenha três arquivos a, foo bar e b, então a linha seria avaliada para:

for logfile in a foo bar b; do

Obviamente, Bash irá definir logfile para a, foo, bare b, que não é o que você queria. Se você pudesse especificar manualmente a entrada para for, você envolveria esses nomes de arquivos entre aspas para resolver o problema.

Para fazer isso automaticamente, a solução é delimitar esses nomes de arquivos com um NUL personagem (que é o que o -print0 opção faz) e, em seguida, dividir a saída com base nesse NUL personagem novamente (que é o que o -d '' em read faz).

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.