Procura por uma string em um arquivo e renomeia vários arquivos para os resultados

1

Eu estou tentando pesquisar recursivamente por meio de uma lista de arquivos e, se o arquivo contiver uma string, renomeie o arquivo para os resultados do grep da referida string.

Os arquivos de amostra contêm o seguinte conteúdo:

file1   
foo bar1

file2
foo bar2

file3
foo bar3

file4
foo bar4

file5
foo bar5

grep + awk retorna os resultados que eu preciso:

$ grep -r "^foo" . | awk '{print $2}'
bar1
bar2
bar3
bar4
bar5

Estou preso a passar esses resultados para um comando mv.

$ grep -r "^foo" . | awk '{print $2}' | xargs -I{} mv {} .
mv: cannot stat 'bar1': No such file or directory
mv: cannot stat 'bar2': No such file or directory
mv: cannot stat 'bar3': No such file or directory
mv: cannot stat 'bar4': No such file or directory
mv: cannot stat 'bar5': No such file or directory

Obrigado antecipadamente. O Gnu / BSD Grep tem os mesmos resultados.

    
por Bert 02.11.2016 / 19:15

3 respostas

1

Eu usaria um shell for-loop:

for match in "$(grep -ro '^foo.*')";do
    echo mv "${match%:*}" "${match#*:}"
done

Isso itera todos os file:matching-substring correspondentes e usa os operadores % e # string para excluir tudo, resp. tudo depois, e incluindo : .

Observe que, se você realmente deseja corresponder a linha inteira em oposição a apenas a substring que corresponde ao padrão, use

for match in $(grep -r '^foo');do

Certifique-se de aspas duplas, pois as correspondências e / ou nomes de arquivos podem conter espaços.

Se você deseja corresponder por um padrão, mas renomeie o arquivo para a segunda palavra na linha correspondente:

for match in "$(grep -ro '^foo.*')";do
    fname=$("echo ${match#*:}|awk '{print $2}'")
    echo mv "${match%:*}" "$fname"
done
    
por 02.11.2016 / 19:36
0

Você pode fazer o que está tentando realizar usando perl:

#!/usr/bin/env perl
use strict;

my $dir = "/path/to/directory";
chdir $dir or die "Cannot open $dir!";

my @files = grep { -f } glob("*");

foreach my $file(@files) {
  open F1, "<", $file or die "Cannot open file $file! $!\n";
  while ( <F1> ){
    chomp;
    my @strings = split(' ');
    if($strings[1] =~ /bar/){
      system("/bin/mv $file $strings[1]");
    }
  }
  close(F1);
}
    
por 02.11.2016 / 20:05
0

find . -type f -exec egrep -il '^foo' {} \; | sort | while IFS='' read -r line; do mv -n "$line" "$(dirname "$line")"'/'"$(egrep -i '^foo' "$line" | awk '{ print $2 }')"; done

    
por 08.11.2016 / 23:21

Tags