Passando a saída analisada de sed para localizar (nessa direção)

4

Bem, eu acho que você pode encontrar dezenas de perguntas sobre esta plataforma como canalizar find saída para sed , mas eu não encontrei nada para a direção inversa até agora. O que eu quero fazer é modificar minha entrada , e então passar para find .

Suponha que eu queira fazer algo como o seguinte, a fim de tornar a vida mais fácil para mim, evitando digitar esses curingas asterisco pesado. (Espero que seja óbvio o suficiente para que a expressão que segue o operador here-string <<< seja planejada para ser substituída por um parâmetro, por exemplo, $1 , em um script posterior. A linha abaixo é meramente para demonstração.)

$ sed 's/ /\*/g' <<< ' foo bar baz ' | find . -type f -iname - 

Esse - no final deste one-liner era supostamente para usar a saída de sed como entrada para find ; no entanto, estendendo a parte find para

... find -D tree . -type f -iname - ... 

revelou que o parâmetro não foi passado para find . Talvez você não possa passar a entrada pré-processada para find usando um canal?

    
por syntaxerror 26.09.2012 / 01:20

2 respostas

5

find não recebe seus args do stdin, ele os pega na linha de comando, então:

find . -iname "$(sed 's/ /\*/g' <<< ' foo bar baz ')"

Isso se tornará:

find . -iname "foo*bar*baz*"

(as aspas são necessárias para impedir que o shell expanda o curinga foo * bar * baz *)

que pode ou não ser o que você esperava obter. por exemplo. se você realmente quisesse arquivos começando com foo, bar ou baz ao invés de arquivos que correspondessem ao padrão 'foo * bar * baz *' então você precisa construir um regexp e usar -regex ou -iregex ao invés de -iname . ou construa um comando de localização mais complicado, como -iname 'foo*' -o -iname 'bar*' -o -iname 'baz*'

alternativamente:

PATTERN='foo bar baz'
PATTERN=$(echo "$PATTERN" | sed -e 's/ /*/g')
# and/or do whatever else you need to do to transform $PATTERN to be what
# you need it to be...
find . -iname "$PATTERN"

Aqui está o one-liner em um script bash. Funciona exatamente da mesma maneira no script que na linha de comando.

$ cat ./test.sh
#! /bin/bash 
find . -iname "$(sed 's/ /\*/g' <<< ' foo bar baz ')"

$ ls -l
total 4
-rw-r--r-- 1 cas cas  0 Sep 26 16:53 doesntmatch
lrwxrwxrwx 1 cas cas 16 Sep 26 16:59 symlink -> xfoo-ybar-zbaz01
-rwxr-xr-x 1 cas cas 69 Sep 26 16:50 test.sh
-rw-r--r-- 1 cas cas  0 Sep 26 16:50 xfoo-ybar-zbaz01
-rw-r--r-- 1 cas cas  0 Sep 26 16:50 xfoo-ybar-zbaz02
-rw-r--r-- 1 cas cas  0 Sep 26 16:50 xfoo-ybar-zbaz03

$ ./test.sh 
./xfoo-ybar-zbaz01
./xfoo-ybar-zbaz03
./xfoo-ybar-zbaz02

$ find . -iname "$(sed 's/ /\*/g' <<< ' foo bar baz ')"
./xfoo-ybar-zbaz01
./xfoo-ybar-zbaz03
./xfoo-ybar-zbaz02

$ find . -iname "*foo*bar*baz*"
./xfoo-ybar-zbaz01
./xfoo-ybar-zbaz03
./xfoo-ybar-zbaz02
    
por 26.09.2012 / 01:31
0

Por que você não usa um loop for?

for n in $(sed 's/ /\*/g' <<< ' foo bar baz '); do find . -iname $n; done
    
por 26.09.2012 / 01:28