El script de PowerShell no comprime los archivos correctos
scripting zip (2)
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
Estoy probando este script que encontré en línea. Mi problema es que, en lugar de comprimir los archivos en la carpeta de destino, está copiando y comprimiendo el contenido de la carpeta de archivos del programa 7-zip. Que podria causar esto? Gracias por adelantado
Si usted (temporalmente) desactiva el
|Out-Null
, verá qué mensaje de error pasa.
$ Files contiene objetos, no solo una matriz de nombres de archivos.
De forma predeterminada, powershell intenta crear una cadena de caracteres utilizando la propiedad
Name
, que no contiene la ruta, por lo que 7zip no puede encontrar los archivos, ya que también se cambia la ruta a la carpeta 7zip (y -receptan la recolección de $ archivos)
Entonces cambia la linea
$Files = Get-Childitem $TargetFolder -Recurse | Where {$_.LastWriteTime -le "$LastWrite"}
y añadir
| Select-Object -ExpandProperty FullName
Un verson ligeramente reformateado de tu fuente:
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
Pase los archivos como
rutas completas
a la función
Zip
, usando su propiedad .FullName (sintaxis de PSv3 +):
Zip C:/Users/Admin/Desktop/TEST.zip $Files.FullName
El problema es que
las instancias de
[System.IO.FileInfo]
devueltas por
Get-ChildItem
situacionalmente
[1] solo se
ajustan a sus
nombres de archivo
, que es lo que sucedió en su caso, por lo que su función
Zip
interpretó los valores de
$toBeZipped
como
relativos a la ubicación actual
, que es
C:/Program Files/7-Zip
en ese punto.
Dicho esto, es
mejor no usar
Set-Location
en su función por completo
, de modo que, en caso de que quiera pasar rutas
relativas
reales, se interpreten correctamente como relativas a la ubicación
actual
:
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]
Cuando la
salida de
Get-ChildItem
se limita a los
nombres de
archivo solamente:
Nota:
-
Afortunadamente, la salida de
Get-Item
siempre se limita a la ruta completa. -
En PowerShell
Core
,
Get-ChildItem
también se limita a la ruta completa , lo que es recomendable, pero no está claro si el cambio fue intencional .
Por lo tanto, lo siguiente
solo se aplica a
Get-ChildItem
en
Windows PowerShell
:
El problema es doble:
-
Incluso los cmdlets incorporados de PowerShell vinculan los argumentos del archivo / directorio (valores de parámetros, en lugar de la entrada a través de la canalización ), no como objetos , sino como cadenas ( este tema de GitHub se está discutiendo para cambiar este comportamiento).
-
Por lo tanto, para una
Get-ChildItem
argumentos sólida, debe asegurarse de que la salida de suGet-ChildItem
coherente con las rutas completas , lo queGet-ChildItem
no garantiza, y es fácil de olvidar cuando se produce una clasificación de solo nombre, incluso de lo que necesita pagar. atención a ello en absoluto.
.FullName
siempre los valores de propiedad
.FullName
lugar es la solución más simple
o, para una operación confiable con
cualquier
proveedor de PowerShell, no solo el sistema de archivos,
.PSPath
.
[System.IO.FileInfo]
instancias
[System.IO.FileInfo]
y
[System.IO.DirectoryInfo]
generadas por un comando
Get-ChildItem
limitan a sus
nombres de
archivo,
si y solo si
:
-
Si se pasan una o más rutas de directorio literales a
-Path
o-Path
(posiblemente como el primer argumento posicional) o no se pasa ninguna ruta (-Path
la ubicación actual); es decir, si se enumeran los contenidos de los directorios. -
y tampoco usa los parámetros
-Exclude
/-Exclude
(si se usa-Filter
no hace ninguna diferencia). -
Por el contrario, si los siguientes también están presentes o no, no hay diferencia:
-
-Filter
(opcionalmente como el segundo argumento posicional, pero tenga en cuenta que al especificar una expresión comodín como*.txt
como el primer argumento posicional (y posiblemente solo) se enlaza con el parámetro-Path
) -
-Recurse
(por sí mismo , pero tenga en cuenta que a menudo se combina con-Exclude
/-Exclude
)
-
Ejemplos de comandos:
# 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