скрипт для фильтрации файлов - PullRequest
0 голосов
/ 06 января 2010

У меня есть каталог, в котором много файлов, я хочу перейти к каждому файлу и открыть его, найти определенное слово, а затем найденное слово скопировать файл в другой каталог.

Спасибо

Ответы [ 6 ]

1 голос
/ 06 января 2010
grep -r "term" . | sed -e 's/:.*//' | uniq | xargs -I {} cp -v {} /target/dir

.. при условии, что у вас есть grep под рукой.

0 голосов
/ 07 января 2010

Хорошо, если я вас правильно понимаю, вы хотите:

  • Переместить файл в определенный каталог
    • В зависимости от того, присутствует ли определенное слово в файле или нет
  • Это должно быть сделано для всех файлов в каталоге

Если я правильно понял, то на самом деле это очень просто.

Краткий ответ:

for %%f in (*) do (
    findstr "foo" "%%f" > NUL 2>&1
    if not errorlevel 1 copy "%%f" "some_directory"
)

Более подробное объяснение:

Прежде всего, перебор набора файлов (да, «все файлы» также набор файлов) можно легко выполнить с помощью команды for:

for %%f in (*) do ...

Затем вы хотите узнать, появляется ли в файле конкретное слово (давайте представим, что оно "foo") или нет. Это можно проверить с помощью команды findstr:

findstr "foo" "%%f"

Теперь по умолчанию будет выводиться каждая строка, где "foo" находится на экране. И, возможно, даже сообщения об ошибках, поэтому мы перенаправляем их в небытие:

> NUL 2>&1

findstr возвращает конкретный числовой код в зависимости от того, была найдена данная строка или нет. В то время как вы обычно не можете видеть это, мы все еще можем проверить это. Этот конкретный код называется уровень ошибки , это предвещает времена Ye Olde DOS или, возможно, даже CP / M. В любом случае, этот уровень ошибки либо 0, либо 1. Если это 0, это означает, что текст был найден, когда он 1, то текст либо не был найден, либо произошла другая ошибка.

Существует специальный синтаксис для проверки уровня ошибки, который имеет небольшую причуду: он проверяет, является ли уровень ошибки по крайней мере определенным числом. Поэтому для тестирования 0 нам нужно инвертировать его, но это не имеет большого значения:

if not errorlevel 1 copy "%%f" "some_directory"

Это перемещает файл в some_directory, но только если уровень ошибки был , а не как минимум 1 , другими словами: ровно 0. Что означает, что текст, который мы искали в файле, был найден .

Собрав все это вместе, теперь это выглядит следующим образом:

for %%f in (*) do (
    findstr "foo" "%%f" > NUL 2>&1
    if not errorlevel 1 copy "%%f" "some_directory"
)

Это было не слишком сложно, не так ли?


P.S .: Мы можем немного сократить это, поскольку язык пакетных файлов имеет специальный синтаксис для выполнения команды только , когда другая команда завершается успешно:

for %%f in (*) do (findstr "foo" "%%f" >NUL 2>&1 && copy "%%f" "some_directory")

Теперь мы собрали его в одну строку. Но так как copy также выводит текст, мы можем переместить перенаправление в конец строки, чтобы поймать как вывод findstr, так и вывод copy:

for %%f in (*) do (findstr "foo" "%%f" && copy "%%f" "some_directory") >NUL 2>&1

И так как это одна строка, нам больше не нужен командный файл (ну, строго говоря, нам это и раньше не нужно), и мы можем сбросить двойной %, чтобы запустить его непосредственно из командной строки. :

for %f in (*) do @(findstr "foo" "%f" && copy "%f" "some_directory") >NUL 2>&1

Я включил @ перед открывающей скобкой, чтобы подавить вывод запущенных команд, иначе ваш экран быстро заполнится запущенными командами. В пакетном файле вы обычно просто включаете @echo off в первой строке.

0 голосов
/ 06 января 2010

при условии использования linux и использования оболочки bash

#!/bin/bash
dest="/destination"
shopt -s nullglob
for file in *
do
   grep "searchterm" "$file" && mv "$file" "$dest"
done
0 голосов
/ 06 января 2010

Простой цикл позаботится об этом за вас:

for x in `grep -l <your pattern> *`
do
     cp $x <new path>/$x
done

Просто добавьте пробелы в имени файла:

grep -l <your pattern> * | while read file
do
     cp $file <new path>/$file
done
0 голосов
/ 06 января 2010

Python

import os
import shutil
for path, dirs, files in os.walk( 'path/to/dir' ):
    for name in files:
        aFileName= os.path.join(path,name)
        with open( aFileName, "r" ) as content:
            if "myword" in content:
                shutil.copy( aFileName, "path/to/other/dir" )

Это должно работать достаточно хорошо. Я не проверял это подробно, но вы можете видеть, как это будет работать.

0 голосов
/ 06 января 2010

Создайте командный файл следующим образом:

FOR /F "usebackq delims==" %%i IN (`findstr /M "xxx_string_to_search_xxx" c:\source\*.*`) DO copy %%i c:\destination\

Он будет искать xxx_string_to_search_xxx в C: \ source и копирует эти файлы в C: \ destination

...