
Estoy intentando buscar recursivamente en una lista de archivos y, si el archivo contiene una cadena, cambiarle el nombre al resultado de grep de dicha cadena.
Los archivos de muestra contienen el siguiente contenido:
file1
foo bar1
file2
foo bar2
file3
foo bar3
file4
foo bar4
file5
foo bar5
grep + awk devuelven los resultados que necesito:
$ grep -r "^foo" . | awk '{print $2}'
bar1
bar2
bar3
bar4
bar5
Estoy atascado al pasar estos resultados a un 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
Gracias de antemano. Gnu/BSD Grep ambos tienen los mismos resultados.
Respuesta1
Yo usaría un bucle for de shell:
for match in "$(grep -ro '^foo.*')";do
echo mv "${match%:*}" "${match#*:}"
done
Esto iterará todas las coincidencias file:matching-substring
y utilizará los operadores de cadena %
y #
para eliminar todo hasta, resp. todo lo posterior, incluido :
.
Tenga en cuenta que si realmente desea hacer coincidir toda la línea en lugar de solo la subcadena que coincide con el patrón, use
for match in $(grep -r '^foo');do
Asegúrese de poner comillas dobles, ya que las coincidencias y/o los nombres de archivos pueden contener espacios.
Si desea hacer coincidir un patrón pero cambiar el nombre del archivo a la segunda palabra en la línea coincidente:
for match in "$(grep -ro '^foo.*')";do
fname=$("echo ${match#*:}|awk '{print $2}'")
echo mv "${match%:*}" "$fname"
done
Respuesta2
Puedes hacer lo que intentas lograr 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);
}
Respuesta3
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