Powershell v2.0을 사용하여 X 일보다 오래된 파일을 삭제하고 싶습니다.
$backups = Get-ChildItem -Path $Backuppath |
Where-Object {($_.lastwritetime -lt (Get-Date).addDays(-$DaysKeep)) -and (-not $_.PSIsContainer) -and ($_.Name -like "backup*")}
foreach ($file in $backups)
{
Remove-Item $file.FullName;
}
그러나 $ backups가 비어 있으면 다음을 얻습니다. Remove-Item : Cannot bind argument to parameter 'Path' because it is null.
난 노력 했어:
- 와 foreach를 보호
if (!$backups)
- 제거 항목 보호
if (Test-Path $file -PathType Leaf)
- 제거 항목 보호
if ([IO.File]::Exists($file.FullName) -ne $true)
이들 중 어느 것도 작동하지 않는 것 같습니다. 목록이 비어있는 경우 foreach 루프가 입력되지 않도록 권장하는 방법은 무엇입니까?
답변
Powershell 3을 사용하면 foreach
명령문이 반복되지 않고 $null
OP에 설명 된 문제가 더 이상 발생하지 않습니다.
로부터 의 Windows PowerShell 블로그 포스트 새로운 V3 언어 특징 :
ForEach 문은 $ null을 반복하지 않습니다.
PowerShell V2.0에서 사람들은 종종 다음에 놀랐습니다.
PS> foreach ($i in $null) { 'got here' }
got here
이 상황은 cmdlet이 개체를 반환하지 않을 때 종종 발생합니다. PowerShell V3.0에서는 $ null을 반복하지 않도록 if 문을 추가 할 필요가 없습니다. 우리는 당신을 위해 그것을 처리합니다.
PowerShell $PSVersionTable.PSVersion.Major -le 2
의 경우 원래 답변은 다음을 참조하십시오.
두 가지 옵션이 있습니다. 나는 주로 두 번째 옵션을 사용합니다.
확인 $backups
하지 마십시오 $null
. If
루프 주위의 간단한 것이 아닌지 확인할 수 있습니다.$null
if ( $backups -ne $null ) {
foreach ($file in $backups) {
Remove-Item $file.FullName;
}
}
또는
$backups
null 배열로 초기화하십시오 . 이렇게하면 마지막 질문에서 “iterate empty array”문제의 모호성을 피할 수 있습니다 .
$backups = @()
# $backups is now a null value array
foreach ( $file in $backups ) {
# this is not reached.
Remove-Item $file.FullName
}
죄송합니다. 코드를 통합하는 예제를 제공하지 않았습니다. 노트 Get-ChildItem
배열에 싸여 cmdlet를. 이것은 또한을 반환 할 수있는 함수와 함께 작동합니다 $null
.
$backups = @(
Get-ChildItem -Path $Backuppath |
Where-Object { ($_.lastwritetime -lt (Get-Date).addDays(-$DaysKeep)) -and (-not $_.PSIsContainer) -and ($_.Name -like "backup*") }
)
foreach ($file in $backups) {
Remove-Item $file.FullName
}
답변
이 게시물은 오래된 게시물이지만 ForEach-Object cmdlet에는 ForEach 키워드를 사용하는 것과 같은 문제가 발생하지 않습니다. 따라서 DIR의 결과를 ForEach로 파이프하고 $ _를 사용하여 파일을 참조하면됩니다.
$backups | ForEach{ Remove-Item $_ }
실제로 파이프를 통해 Dir 명령 자체를 전달하고 다음과 같이 변수를 할당하지 않아도됩니다.
Get-ChildItem -Path $Backuppath |
Where-Object {
($_.lastwritetime -lt (Get-Date).addDays(-$DaysKeep)) -and `
(-not $_.PSIsContainer) -and ($_.Name -like "backup*")
} |
ForEach{ Remove-Item $_ }
가독성을 위해 줄 바꿈을 추가했습니다.
가독성을 위해 ForEach / In과 같은 일부 사람들을 이해합니다. 때로는 ForEach-object가 약간 털이 나올 수 있습니다. 특히 $ _ 참조를 따르기가 어려워 중첩되어있는 경우 특히 그렇습니다. 어쨌든 이와 같은 작은 작업에는 완벽합니다. 많은 사람들은 또한 그것이 더 빠르다고 주장하지만 나는 그것이 단지 약간이라는 것을 알았습니다.
답변
쿼리를 두 번 실행하여 한 번 파일을 가져오고 get-ChilItem을 캐스팅하여 배열을 반환하여 파일을 계산하는 솔루션을 개발했습니다 (사실이 작동하지 않는 경우 $ backups를 배열로 캐스팅) .
단일 쿼리 솔루션에 대해 아는 사람이 있다면 적어도 예상대로 작동합니다 (수십 개 이상의 파일이 없기 때문에 성능이 문제가되어서는 안됩니다).
$count = @(Get-ChildItem -Path $zipFilepath |
Where-Object {($_.lastwritetime -lt (Get-Date).addDays(-$DaysKeep)) -and (-not $_.PSIsContainer) -and ($_.Name -like $partial + "*")}).count;
if ($count -gt 0)
{
$backups = Get-ChildItem -Path $zipFilepath |
Where-Object {($_.lastwritetime -lt (Get-Date).addDays(-$DaysKeep)) -and (-not $_.PSIsContainer) -and ($_.Name -like $partial + "*")};
foreach ($file in $backups)
{
Remove-Item $file.FullName;
}
}
답변
배열에 내용이 있는지 평가하려면 다음을 사용하십시오.
if($backups.count -gt 0) { echo "Array has contents" } else { echo "Array is empty" }
변수가 존재하지 않으면 Powershell은 단순히 변수를 거짓으로 평가하므로 존재 여부를 확인할 필요가 없습니다.