У меня есть список файлов, которые пропали где-то в нашей системе на работе. У меня также есть папка, содержащая 41 файл журнала, в который добавляется до 46 МБ, и, надеюсь, в нем есть записи, относящиеся к отсутствующим файлам. Как я могу grep эти файлы журнала для любого значения в моем списке?

Список структурирован как один файл на строку без расширения файла. Журналы, кажется, имеют структуру, но я пока не совсем знаком с этой структурой. Он содержит имена файлов и пути, а также то, что с ним было сделано.

Я знаю, что могу cat * все файлы журнала и передать его в grep . Я, вероятно, буду использовать -A и -B чтобы получить небольшой контекст из файлов журнала, когда имя найдено. Я использую GnuWin32 на окнах, чтобы я мог связать это с Powershell, но я думаю, что для этого потребуется, чтобы одно имя файла заняло все 46 МБ, а когда я перехожу к следующему имени файла, я начинаю заново. У меня есть 1830 файлов в списке, поэтому, если мне придется начинать все сначала, я буду читать 46 МБ столько раз, что буду иметь дело с ГБ повторяющихся данных. Это кажется неэффективным.

Я полагаю, я мог бы создать большое регулярное выражение из файлов 1830 года или собрать их вместе и запустить один раз для журналов, но возможно ли это? Регулярное выражение будет почти 30 КБ (1830 файлов * средняя длина имени файла около 16 символов = 29280 байт, не говоря уже о 1830 байтах символов канала).

Изменить: вот что я делаю сейчас, когда я нахожусь в папке журналов, и список находится на одну папку назад:

$logs = gc *
$notfound = gc ../notfound.txt
$logs | % { $i = 0; while ($i -lt $notfound.Count) { if ($_ -contains $notfound[$i]) { echo $_ }; $i++; } } | out-file C:\discovered.txt

Это полностью PowerShell. Я готов использовать любой инструмент, чтобы ускорить это, потому что сейчас во всех файлах журнала есть 550991 строка и 1830 имен файлов, так что этот подход делает 1 008 313 530 сравнений. Это все в памяти, так что, по крайней мере, у меня нет дискового ввода-вывода, замедляющего меня. Я мог бы вырваться из этого while если if станет правдой, но я все еще собираюсь сделать так много сравнений, что я не уверен, что оптимизация действительно принесет пользу. Это уже работает в течение получаса. Я в порядке с переписыванием моего подхода от линии 1, если я могу сделать это прежде, чем я уеду домой на выходные.

1 ответ1

0

Было бы эффективнее извлечь имена файлов из журналов с помощью регулярного выражения и посмотреть, есть ли каждое из них в вашем списке. Это может выглядеть примерно так:

$notfound = gc ../notfound.txt
gc * |
        select-string -AllMatches '\\(?<filename>[^\\]+)\.txt' | 
        select -ExpandProperty Matches |
        % { $_.Groups['filename'].Value } |
        ? { $notfound -contains $_ } |
        out-file C:\discovered.txt

Я ищу файлы, которые выглядят как "\something.txt". Вам придется изменить это.

Если он все еще слишком медленный, а ваш необнаруженный список очень большой, то, возможно, будет более эффективно загрузить его в .Net HashSet, но я бы не стал этого делать, если в этом нет необходимости.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .