Найдите строку в файле и переименуйте несколько файлов в результаты

Я пытаюсь рекурсивно искать список файлов, и если файл содержит строку, переименуйте файл в результаты 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 имеют одинаковые результаты.

3 Solutions collect form web for “Найдите строку в файле и переименуйте несколько файлов в результаты”

Я бы использовал оболочку для цикла:

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

Это приведет к итерации всего совпадающего file:matching-substring и использования операторов строк % и # чтобы удалить все до, соответственно. все после, и в том числе :

Обратите внимание: если вы действительно хотите сопоставить всю строку, а не только подстроку, которая соответствует шаблону, используйте

 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 

Вы можете делать то, что вы пытаетесь выполнить с помощью 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); } 

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

  • Необходимо отформатировать 5 дисков параллельно
  • Мне нужно "| xargs -n 1 ", чтобы обойти xargs -I побочный эффект?
  • zsh "echo SomeText >> ** / filename" в других оболочках
  • basename не работает должным образом
  • Как удалить команды в истории, соответствующие заданной строке?
  • Как создать бесконечный поток строк в bash
  • Как вы можете перемещать или копировать определенные файлы из списка текстовых файлов
  • Перемещение подкаталога в новый родительский каталог, где новое имя каталога увеличивается на 1
  • Как перемещаться по xargs, где каждый скрипт использует общую переменную env
  • подстановка процесса для открытия списка файлов с приложением
  • xargs git: пропустить ввод пользователя
  • Linux и Unix - лучшая ОС в мире.