git-bash come gestire gli spazi nei nomi dei file


1

Ho scritto il seguente script per eseguire git-bash sotto 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

Il problema è che grep si strozza quando un nome file ha uno spazio al suo interno. Pensavo che le virgolette dovessero prendersene cura, ma non è cooperativo.

Idee?

In alternativa, puoi dire cosa sto cercando di fare. Qualsiasi altro suggerimento sarebbe benvenuto.

Risposte:


3

Soluzione 1

La soluzione più vicina è da usare find con -print0 e leggi l'output con while read …:

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

Continua a usare "$logfile" con le virgolette, come dovresti sempre quando usi le variabili.

Soluzione 2

Un'altra soluzione sarebbe quella di non usare find del tutto e basta grep eseguire su più file:

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

Qui, globstar abilita la corrispondenza ricorsiva delle directory con **. Dovresti impostare nullglob per evitare errori se una di queste estensioni di file non esiste.

Questo funziona solo per un insieme limitato di file, poiché è possibile raggiungere la lunghezza massima degli argomenti della riga di comando.

Perché l'errore si verifica?

Non dovresti mai correre for sull'output di find (o lso qualsiasi altra funzione che restituisce nomi di file con spazi bianchi). Leggere Questo articolo per maggiori informazioni sul motivo per cui questo è un problema e cosa può essere fatto per risolverlo.

In breve, Bash divide gli argomenti in spazi vuoti. Immagina di avere tre file, a, foo bar e b, quindi la linea sarebbe valorizzata a:

for logfile in a foo bar b; do

Ovviamente, Bash imposterà logfile a a, foo, bar, e b, che non è quello che volevi. Se fosse possibile specificare manualmente l'input for, dovresti avvolgere questi nomi di file tra virgolette per risolvere il problema.

Per fare ciò automaticamente, la soluzione è di delimitare questi nomi di file con a NUL personaggio (che è ciò che il -print0 opzione fa) e quindi dividere l'output in base a quello NUL carattere di nuovo (che è ciò che il -d '' nel read lo fa).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.