Bash Shell脚本:如何从大型语料库复制具有特定字符串的文件

Bash Shell脚本:如何从大型语料库复制具有特定字符串的文件,bash,shell,ack,Bash,Shell,Ack,我有一个小错误,不知道如何解决它。我想从包含许多文件的大文件夹中复制文件,其中的文件包含特定的字符串。为此,我使用grep、ack或(在本例中)ag。当我在文件夹中时,它匹配没有问题,但是当我想在下面的脚本中循环文件时,它不会循环匹配。下面是我的脚本: ag -l "${SEARCH_QUERY}" "${INPUT_DIR}" | while read -d $'\0' file; do echo "$file" cp "${file}" "${OUTPUT_DIR}/${fi

我有一个小错误,不知道如何解决它。我想从包含许多文件的大文件夹中复制文件,其中的文件包含特定的字符串。为此,我使用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是找到的文件应该复制到的文件夹。你在做什么的时候有什么问题吗

编辑: 谢谢你的建议!我现在选择了这个,因为它也会在子文件夹中查找文件,并保存一个包含所有文件的列表

ag -l "${SEARCH_QUERY}" "${INPUT_DIR}" > "output_list.txt" 
while read file
do
    echo "${file##*/}"
    cp "${file}" "${OUTPUT_DIR}/${file##*/}"
done < "output_list.txt"
ag-l“${SEARCH\u QUERY}”${INPUT\u DIR}”>“output\u list.txt”
读取文件时
做
回显“${file##*/}”
cp“${file}”“${OUTPUT_DIR}/${file##*/}”
完成<“输出列表.txt”

最好使用
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
find“${INPUT_DIR}”-name“*.*”| xargs grep-l“${SEARCH_QUERY}”>/tmp/file_list.txt
读取文件时
做
回显“$file”
cp“${file}”“${OUTPUT_DIR}/${file}”
完成
或另一种选择:

 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
grep-l“${SEARCH\u QUERY}”“${INPUT\u DIR}/*.*”>/tmp/file\u list.txt
读取文件时
做
回显“$file”
cp“${file}”“${OUTPUT_DIR}/${file}”
完成
如果我理解正确,那么您必须

  • 将读取分隔符调整为
    '\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)
读取文件时
;做
回显“$file”
cp“$file”“$OUTPUT\u DIR/$file”

完成<如果您不介意只做一行,那么

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

  • -l
    只打印文件名,不打印其他内容
  • -r
    递归搜索CWD和所有子目录
  • 交替匹配这些作品:“一”或“二”或“三”
  • |
    grep
    的输出通过管道传输到
    xargs
  • -I xxx
    文件名保存在
    xxx
    中,它只是一个别名
  • -P 0
    并行运行所有命令(
    cp
  • cp
    每个文件
    xxx
    dist
    目录

  • 谢谢,但我想你是说循环中的“$line”而不是“$file”,我认为在大文件夹中使用grep时,“find”相当慢?这就是为什么我想使用ack或ag。是的,我刚刚用两个选项修改了我的答案。如果您还需要搜索子目录中的文件,第一个选项将对您有所帮助。谢谢,我使用了您的第二个选项,并使用“ag”(也使用子文件夹)进行了一些修改。我的旧解决方案中的一个问题是,我没有为新解决方案删除源文件的路径。