
Ich versuche, eine Liste von Dateien rekursiv zu durchsuchen und, wenn die Datei eine Zeichenfolge enthält, die Datei in die Grep-Ergebnisse dieser Zeichenfolge umzubenennen.
Die Beispieldateien enthalten folgenden Inhalt:
file1
foo bar1
file2
foo bar2
file3
foo bar3
file4
foo bar4
file5
foo bar5
grep + awk geben die Ergebnisse zurück, die ich brauche:
$ grep -r "^foo" . | awk '{print $2}'
bar1
bar2
bar3
bar4
bar5
Ich kann diese Ergebnisse nicht an einen MV-Befehl übergeben.
$ 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
Vielen Dank im Voraus. Gnu/BSD Grep haben beide die gleichen Ergebnisse.
Antwort1
Ich würde eine Shell-For-Schleife verwenden:
for match in "$(grep -ro '^foo.*')";do
echo mv "${match%:*}" "${match#*:}"
done
Dadurch werden alle Übereinstimmungen durchlaufen file:matching-substring
und mithilfe der %
Zeichenfolgenoperatoren und #
alles bis bzw. alles danach und einschließlich gelöscht :
.
Beachten Sie, dass wenn Sie wirklich die ganze Zeile abgleichen wollen und nicht nur die Teilzeichenfolge, die dem Muster entspricht, verwenden Sie
for match in $(grep -r '^foo');do
Stellen Sie sicher, dass Sie doppelte Anführungszeichen verwenden, da Übereinstimmungen und/oder Dateinamen Leerzeichen enthalten können.
Wenn Sie eine Übereinstimmung nach einem Muster erzielen möchten, die Datei aber in das zweite Wort in der übereinstimmenden Zeile umbenennen möchten:
for match in "$(grep -ro '^foo.*')";do
fname=$("echo ${match#*:}|awk '{print $2}'")
echo mv "${match%:*}" "$fname"
done
Antwort2
Sie können das gewünschte Ergebnis mit Perl erzielen:
#!/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);
}
Antwort3
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