7

Я попытался сделать простую вещь с PowerShell, найти файлы, которые занимают больше всего места на диске. Я использовал ls + sort и ... это заняло у меня навсегда.

Иногда я использую далеко менеджер и по сравнению с PowerShell это выглядит намного быстрее и стабильнее.

Хорошо, он основан на .NET, но .NET не такой медленный. Я ожидаю увидеть что-то легкое и быстрое! Это консоль!

Еще одна вещь, я хотел бы иметь что-то вроде IEnumerable в PowerShell, чтобы сразу увидеть результаты. Возможно ли достичь? Это может немного помочь, ожидая результатов, потому что иногда я думаю, что это просто тусуется.

РЕДАКТИРОВАТЬ

Я делаю что-то подобное

ls -Recurse -ErrorAction SilentlyContinue | sort -Property Size | select -First 10

И я предполагаю, что это может занять ДНИ.

РЕДАКТИРОВАТЬ

Просто для сравнения.

Код C # занял у меня около 2 мин. Конечно, он не идеален и не обрабатывает все файлы, но обработал по крайней мере> 95%.

void Main()
{
    GetFilesSize(@"C:\").OrderByDescending(x => x).Take(10).ToList();
}

public IEnumerable<long> GetFilesSize(string directory)
{
    var accessDenied = false;
    var dirList = new string[0]; 
    try
    {
        dirList = Directory.GetDirectories(directory);
    }
    catch{
        accessDenied = true;
    }

    if(accessDenied) yield break;

    foreach (var dir in dirList)
    {
        foreach (var size in GetFilesSize(dir))
        {
            yield return size;
        }
    }

    foreach (var fileName in Directory.GetFiles(directory))
    {
        if(fileName.Length>=260) continue;
        yield return new FileInfo(fileName).Length;
    }
}

2 ответа2

12

PowerShell - это программа, написанная на .Net, но она использует интерфейсы для множества различных интерпретаторов и сред выполнения, когда она на самом деле работает. Это оболочка, так же как и BASH, хотя она написана на C и ничего не говорит о исполняемых в ней двоичных файлах и сценариях. Исполняемыми файлами могут быть код .Net, команды VDM/CMD, команды оболочки * nix, VB/C/WSScript, вызовы WMI, неуправляемые интерфейсы API, файлы JAR или что-либо еще. Эти варианты влияют на производительность кода, выполняемого внутри оболочки, а не на язык, на котором написана оболочка.

Похоже, у вас возникли трудности с выполнением определенной команды. Поэтому лучше задать вопрос: почему ls сортируется медленно, когда вызывается из PowerShell? Когда мы копаем глубже, мы обнаруживаем, что ls - это псевдоним Get-ChildItem, который возвращает массив объектов, содержащий System.IO.DirectoryInfo объекты.

PS C:\Windows\system32> $x=Get-ChildItem ./
PS C:\Windows\system32> $x.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array 

PS C:\Windows\system32> $x[1].GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     DirectoryInfo                            System.IO.FileSystemInfo   

PS C:\Windows\system32>

Вы можете получить результат ls , а затем передать его в вызов Sort-Object и он будет вести себя в основном так, как это делает IEnumerable.

Обратите внимание, что IEnumerable ничего не делает для производительности. Возможно, вы путаете его с IQueryable, который определяет, но не выполняет запрос до самой последней секунды, предположительно после того, как он был украшен операциями фильтрации и сортировки, как .Net делает через LinQ to Objects. В этом случае, поскольку Get-ChildItem не предлагает оптимизированный механизм запросов или индексированный источник данных, вы не можете реально сравнивать современные операции базы данных со списками каталогов.

Итак, в конечном итоге, попробуйте что-то вроде:ls ./ -recurse | Sort-Object Name -descending Для меня, ориентируясь на System32, обработка и сортировка 54430 файлов занимает около 20 секунд.

Наконец, обратите внимание, что вы сильно ударили по производительности, когда попытаетесь перечислить каталог, к которому у вас нет личного доступа, поэтому убедитесь, что вы не возвращаетесь в места, куда вам не разрешено ходить, иначе вы будете страдать. + второе ожидание каждого.

Надеюсь, это поможет.

6

PowerShell создан, чтобы быть удобным, а не быстрым. Это компромисс - он работает за кулисами, поэтому пользователь должен делать меньше. Выполнение большей работы замедляет работу.

Обратите внимание, что ваш код PowerShell состоит из одной строки, чтобы сделать больше, чем ваш код C # в 15 строк.

Это делает больше - даже если вы не используете это.

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

ls в PowerShell возвращает объекты [FileInfo] и [DirectoryInfo] - каждый должен быть создан, и каждый должен запросить файл, чтобы заполнить другие поля, такие как CreationTime и LastWriteTime и Extension and Length, а поля времени должны создать [DateTime] объекты.

Это намного медленнее для каждого файла. Это стоит включить другие опции, даже если вы их не используете - ваш код PowerShell может измениться, чтобы принять размер первых 10 файлов, сделанных в январе, с простым изменением, без других командлетов или инструментов, и при этом оставаться одной строкой, код C # должен быть переписан, запрашивать время создания, переносить время создания и размер в сортировку и так далее.

Причина, по которой вы не видите результаты сразу, заключается в том, что вы | sort Это делает это невозможным. Что если вы сразу начали выводить результаты, но последний найденный файл нужно отсортировать на первый план? Тогда вывод будет неправильным - IEnumerable ничего не может с этим поделать, | sort должна собрать все входные данные, прежде чем она сможет что-либо выводить. Ваш вид быстрее, потому что он сортирует мелочи

Ваш код .Net может выполнять саму сортировку быстрее, потому что он сортирует перечислимое из [long], ему не нужно выполнять поиск свойств.

В целом, ваш код делает намного меньше, а выполнение меньше занимает меньше времени. Но вам потребовалось больше времени, чтобы написать, и он менее гибок и более сфокусирован. Компромисс.

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