Скрипт PowerShell не архивирует правильные файлы - PullRequest
0 голосов
/ 20 ноября 2018
 Function Zip
{
    Param
    (
        [string]$zipFile
        ,
        [string[]]$toBeZipped
    )
    $CurDir = Get-Location
    Set-Location "C:\Program Files\7-Zip"
    .\7z.exe A -tzip $zipFile $toBeZipped | Out-Null
    Set-Location $CurDir
}
$Now = Get-Date
$Days = "60"
$TargetFolder = "C:\users\Admin\Downloads\*.*"
$LastWrite = $Now.AddDays(-$Days)
$Files = Get-Childitem $TargetFolder -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}
$Files
Zip C:\Users\Admin\Desktop\TEST.zip $Files

Я тестирую этот скрипт, который нашел в Интернете.Моя проблема заключается в том, что вместо архивирования файлов в целевой папке происходит копирование и архивирование содержимого папки с 7-zip.Что может вызвать это?Заранее спасибо

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

Если вы (временно) отключите |Out-Null, вы увидите, какие сообщения об ошибках передаются.
$ Файлы содержат объекты, а не только массив имен файлов.

По умолчанию powershell пытается упорядочить это, используя свойство Name, которое не содержит пути - поэтому 7zip не может найти файлы, так как вы также меняете путь к папке 7zip (и -recurse collection)$ files)

Итак, измените строку

$Files = Get-Childitem $TargetFolder -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}

и добавьте

| Select-Object -ExpandProperty FullName

Немного переформатированный источник вашего источника:

Function Zip{
    Param (
        [string]$zipFile,
        [string[]]$toBeZipped
    )
    & "C:\Program Files\7-Zip\7z.exe" A -tzip $zipFile $toBeZipped | Out-Null
}
$Days = "60"
$LastWrite = (Get-Date).Date.AddDays(-$Days)

$TargetFolder = "$($ENV:USERPROFILE)\Downloads\*"

$Files = Get-Childitem $TargetFolder -Recurse | 
   Where {$_.LastWriteTime -le $LastWrite} | 
     Select-Object -ExpandProperty FullName
$Files
Zip "$($ENV:USERPROFILE)\Desktop\TEST.zip" $Files
0 голосов
/ 20 ноября 2018

Передайте файлы как полные пути в функцию Zip, используя их свойство .FullName (синтаксис PSv3 +):

Zip C:\Users\Admin\Desktop\TEST.zip $Files.FullName

Проблема в том, что экземпляры [System.IO.FileInfo], возвращаемые Get-ChildItem ситуационно [1] , преобразуются в их только имена файлов ,что и произошло в вашем случае, поэтому ваша функция Zip затем интерпретировала значения $toBeZipped как относительно текущего местоположения , которое в этой точке равно C:\Program Files\7-Zip.

Тосказал, что лучше не использовать Set-Location в вашей функции в целом , так что в случае, если вы do хотите передать фактические относительные пути, ониправильно интерпретируется как относительно текущего местоположения:

Function Zip {
    Param
    (
        [Parameter(Mandatory)] # make sure a value is passed          
        [string]$zipFile
        ,
        [Parameter(Mandatory)] # make sure a value is passed
        [string[]]$toBeZipped
    )
    # Don't change the location, use & to invoke 7z by its full path.
    $null = & "C:\Program Files\7-Zip\7z.exe" A -tzip $zipFile $toBeZipped
    # You may want to add error handling here.
}

[1] Когда Get-ChildItem вывод преобразуется в файл только имена :

Примечание:

Следовательно, относится только к Get-ChildItem в Windows PowerShell :

Проблема двоякая:

  • Даже встроенные командлеты PowerShell связывают файл / каталог аргументы (значения параметров - в отличие от ввода через конвейер ), а не объекты , но как строки (изменение этого поведения обсуждается в этой проблеме GitHub ).

  • Следовательно, для надежной передачи аргументоввам нужно убедиться, что ваш Get-ChildItem вывод последовательно преобразуется в полных путей , что Get-ChildItem не дает не гарантии - и легко забыть, когда только для имени Струнизация происходит даже из-за того, что вам нужно обратить на это внимание вообще.

Всегда передавать значения свойства .FullName вместо этого - самый простой обходной путь или, для надежной работы с любым поставщиком PowerShell, а не только с файловой системой, .PSPath.

[System.IO.FileInfo] и [System.IO.DirectoryInfo] экземпляры, выводимые командой Get-ChildItem, преобразуются в их файл имена * только 1122 *, тогда и только тогда, когда :

  • Если один или несколько литеральных путей к каталогам передаются в -LiteralPath или -Path (возможно, в качестве 1-го позиционногоаргумент) или путь вообще не указан не пройдено (цель - текущее местоположение);то есть, если перечислено содержимое каталогов.

  • и не также используют-Include / -Exclude параметры (используется ли -Filter, составляет нет разницы).

  • В отличие от этого, следующие или неттакже присутствует разница no :

    • -Filter (необязательно в качестве позиционного аргумента 2nd , но обратите внимание, что указывается выражение подстановочного знака, такое как *.txtпоскольку 1-й (и, возможно, только) позиционный аргумент связывается с параметром -Path)
    • -Recurse (самим , но обратите внимание, что он часто комбинируетсяс -Include / -Exclude)

Примеры команд:

# NAME-ONLY stringification:

Get-ChildItem | % ToString # no target path

Get-ChildItem . | % ToString # path is literal dir.

Get-ChildItem . *.txt | % ToString  # path is literal dir., combined with -Filter

# FULL PATH stringification:

Get-ChildItem foo* | % ToString # non-literal path (wildcard)

Get-ChildItem -Recurse -Include *.txt | % ToString # use of -Include

Get-ChildItem file.txt | % ToString # *file* path
...