Como lidar com espaços em nomes de arquivos no Git Bash

Como lidar com espaços em nomes de arquivos no Git Bash

Eu escrevi o seguinte script para ser executado no 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 contém um espaço. Achei que as aspas duplas deveriam resolver isso, mas não é uma cooperação.

Ideias?

Responder1

Solução 1

A solução mais próxima é usar findwith -print0e ler 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"aspas, como sempre deve fazer ao usar variáveis.

Solução 2

Outra solução seria não usar findnada e apenas deixar greprodar em vários arquivos:

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

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

Porém, isso funciona apenas para um conjunto limitado de arquivos, pois você pode atingir o comprimento máximo dos argumentos da linha de comando.

Por que o erro acontece?

Você nunca deve executar forna saída de find(ou ls, ou qualquer outra função que produza nomes de arquivos com espaços em branco). LerEste artigopara obter mais informações sobre por que isso é um problema e o que pode ser feito para resolvê-lo.

Resumindo, o Bash divide os argumentos por espaços em branco. Imagine que você tem três arquivos, ae foo bar, bentão a linha seria avaliada como:

for logfile in a foo bar b; do

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

Para fazer isso automaticamente, a solução é delimitar esses nomes de arquivos com um NULcaractere (que é o que a -print0opção faz) e então dividir a saída com base nesse NULcaractere novamente (que é o que o -d ''in readfaz).

informação relacionada