Передайте файлы как полные пути в функцию 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