Рекурсивно архивировать все файлы определенного типа из powershell - PullRequest
0 голосов
/ 15 сентября 2018

Есть ли способ использовать сценарий Compress-Archive, который при запуске по пути:

  1. архивирует все файлы, соответствующие фильтру по шаблону (например, * .doc)
  2. архивирует такие файлы в текущей папке и во всех дочерних папках
  3. сохраняет относительную структуру папок (хотя можно использовать относительную или абсолютную)

У меня возникли проблемыпусть он выполнит все три из них одновременно.

Редактировать:

Следующие фильтры и рекурсы, но не поддерживают структуру папок

Get-ChildItem -Path ".\" -Filter "*.docx" -Recurse |
Compress-Archive -CompressionLevel Optimal -DestinationPath "$pwd\doc.archive-$(Get-Date -f yyyyMMdd.hhmmss).zip"

Этот элемент не рекурсивно:

Compress-Archive -Path "$pwd\*.docx" -CompressionLevel Optimal -DestinationPath "$pwd\doc.archive-$(Get-Date -f yyyyMMdd.hhmmss).zip"

В какой-то момент у меня была команда, которая рекурсивна, но не фильтрует, но не может вернуться к ней сейчас.

1 Ответ

0 голосов
/ 15 сентября 2018

К сожалению, Compress-Archive довольно ограничен в Windows PowerShell v5.1 / PowerShell Core 6.1.0:

  • Единственный способ сохранить подкаталогдерево передается путь к каталогу в Compress-Archive.

    • К сожалению, это обеспечивает отсутствие включения / исключения механизм выбора только подмножествафайлов.

    • Кроме того, результирующий архив будет внутренне содержать как единый корневой каталог с именем для входного каталога (например, если вы передадите C:\temp\foo в * 1024)*, результирующий архив будет содержать один каталог foo, содержащий поддерево входного каталога - в отличие от содержимого C:\temp\foo content на верхнем уровне).

    • Невозможно сохранить абсолютных путей.

  • Громоздкий обходной путь заключается в создании временной копииваше дерево каталогов с только интересующими файлами (Copy-Item -Recurse -Filter *.docx . $env:TEMP\tmpDir; Compress-Archive $env:TEMP\tmpDir out.zip - обратите внимание, чтоt пусто dirs.будет включен)

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

Возможно, вам будет лучше с альтернативами :

  • Используйте .NET v4.5+ [System.IO.Compression.ZipFile] и [System.IO.Compression.ZipFileExtensions] типов непосредственно.
    В Windows PowerShell, в отличие от PowerShell Core , вы чаще всего загружаете соответствующую сборку вручную сAdd-Type -AssemblyName System.IO.Compression - см. Ниже.

  • Используйте внешние программы, такие как 7-Zip


Решениепроблема с прямым использованием .NET v4.5 + [System.IO.Compression.ZipFile] класс:

Примечание:

  • В Windows PowerShell, в отличие отPowerShell Core , вы чаще всего загружаете соответствующую сборку вручную с помощью Add-Type -AssemblyName System.IO.Compression.

  • Поскольку PowerShell не поддерживает неявное использование extension методов, начиная с Windows PowerShell v5.1 / PowerShell Core 6.1.0, также необходимо явно использовать класс [System.IO.Compression.ZipFileExtensions].

# Windows PowerShell: must load assembly System.IO.Compression manually.
Add-Type -AssemblyName System.IO.Compression

# Create the target archive via .NET to provide more control over how files
# are added.
# Make sure that the target file doesn't already exist.
$archive = [System.IO.Compression.ZipFile]::Open(
  "$pwd\doc.archive-$(Get-Date -f yyyyMMdd.hhmmss).zip",
  'Create'
)

# Get the list of files to archive with their relative paths and
# add them to the target archive one by one.
$useAbsolutePaths = $False # Set this to true to use absolute paths instead.
Get-ChildItem -Recurse -Filter *.docx | ForEach-Object {
    # Determine the entry path, i.e., the archive-internal path.
    $entryPath = (
          ($_.FullName -replace ([regex]::Escape($PWD.ProviderPath) + '[/\\]'), ''), 
          $_.FullName
        )[$useAbsolutePaths]
    $null = [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile(
      $archive, 
      $_.FullName, 
      $entryPath
    )
  }

# Close the archive.
$archive.Dispose()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...