Shell Script: Как скопировать файлы с определенной строкой из большого корпуса - PullRequest
0 голосов
/ 06 июля 2018

У меня небольшая ошибка, и я не знаю, как ее решить. Я хочу скопировать файлы из большой папки со многими файлами, где файлы содержат определенную строку. Для этого я использую grep, ack или (в этом примере) ag. Когда я нахожусь в папке, это сопоставляет без проблем, но когда я хочу сделать это с циклом по файлам в следующем скрипте, оно не проходит по совпадениям. Вот мой сценарий:

ag -l "${SEARCH_QUERY}" "${INPUT_DIR}" | while read -d $'\0' file; do
    echo "$file"
    cp "${file}" "${OUTPUT_DIR}/${file}"
done

SEARCH_QUERY содержит строку, которую я хочу найти внутри файлов, INPUT_DIR - это папка, в которой находятся файлы, OUTPUT_DIR - папка, в которую следует скопировать найденные файлы. Что-то не так с while do?

EDIT: Спасибо за предложения! Я взял этот сейчас, потому что он также ищет файлы в подпапках и сохраняет список со всеми файлами.

ag -l "${SEARCH_QUERY}" "${INPUT_DIR}" > "output_list.txt" 
while read file
do
    echo "${file##*/}"
    cp "${file}" "${OUTPUT_DIR}/${file##*/}"
done < "output_list.txt"

Ответы [ 3 ]

0 голосов
/ 06 июля 2018

Если я правильно понимаю поведение ag , тогда вам нужно

  • установите разделитель чтения на '\n' или
  • используйте ag -0 -l для принудительного разграничения на '\0'

чтобы решить проблему в вашем цикле.

Кроме того, вы можете использовать следующий скрипт, основанный на find вместо ag.

while read file; do
    echo "$file"
    cp "$file" "$OUTPUT_DIR/$file"
done < <(find "$INPUT_DIR" -name "*$SEARCH_QUERY*" -print)
0 голосов
/ 06 июля 2018

если вы не против сделать это всего за одну строку , тогда

grep -lr 'ONE\|TWO\|THREE' | xargs -I xxx -P 0 cp xxx dist/

руководство:

  1. -l просто напечатайте имя файла и ничего больше
  2. -r поиск рекурсивно CWD и все подкаталоги
  3. поочередно соответствуют этим произведениям: ' ONE ' или ' TWO ' или ' THREE '
  4. | трубы на выходе от grep до xargs
  5. -I xxx имя файла сохраняется в xxx это просто псевдоним
  6. -P 0 выполнить всю команду (= cp) параллельно (= как можно быстрее)
  7. cp каждый файл xxx в каталог dist
0 голосов
/ 06 июля 2018

Лучше реализовать это, как показано ниже, с помощью команды find:

  find "${INPUT_DIR}" -name "*.*" | xargs grep -l "${SEARCH_QUERY}" > /tmp/file_list.txt

  while read file
  do
     echo "$file"
     cp "${file}" "${OUTPUT_DIR}/${file}"
  done < /tmp/file_list.txt
  rm /tmp/file_list.txt

или другой вариант:

 grep -l "${SEARCH_QUERY}" "${INPUT_DIR}/*.*" > /tmp/file_list.txt 

 while read file
  do
     echo "$file"
     cp "${file}" "${OUTPUT_DIR}/${file}"
  done < /tmp/file_list.txt

  rm /tmp/file_list.txt
...