
파일 목록을 통해 재귀적으로 검색을 시도하고 있으며 파일에 문자열이 포함되어 있으면 파일 이름을 해당 문자열의 grep 결과로 바꿉니다.
샘플 파일에는 다음 내용이 포함되어 있습니다.
file1
foo bar1
file2
foo bar2
file3
foo bar3
file4
foo bar4
file5
foo bar5
grep + awk는 필요한 결과를 반환합니다.
$ grep -r "^foo" . | awk '{print $2}'
bar1
bar2
bar3
bar4
bar5
이 결과를 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
미리 감사드립니다. Gnu/BSD Grep은 모두 동일한 결과를 갖습니다.
답변1
쉘 for-loop를 사용하겠습니다.
for match in "$(grep -ro '^foo.*')";do
echo mv "${match%:*}" "${match#*:}"
done
그러면 모든 일치 항목이 반복 file:matching-substring
되고 %
및#
resp까지 모든 항목을 삭제합니다. .:
패턴과 일치하는 하위 문자열만 일치시키는 것이 아니라 전체 행을 일치시키려면 다음을 사용하십시오.
for match in $(grep -r '^foo');do
일치 항목 및/또는 파일 이름에 공백이 포함될 수 있으므로 큰따옴표를 사용하십시오.
하나의 패턴으로 일치시키고 싶지만 파일 이름을 일치하는 줄의 두 번째 단어로 바꾸는 경우:
for match in "$(grep -ro '^foo.*')";do
fname=$("echo ${match#*:}|awk '{print $2}'")
echo mv "${match%:*}" "$fname"
done
답변2
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);
}
답변3
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