2016-06-28 6 views
3

폴더에서 프로그래밍 방식으로 (예 : Powershell을 사용하여) 특정 일수보다 오래된 파일을 삭제해야합니다.xx 일보다 오래된 파일을 삭제하십시오.

나는이 작업을 수행하는 간단한 스크립트를 작성했지만, 문제는 폴더에있는 파일의 양 때문에 삭제를 시작하는 데 문제가있는 것 같습니다.

일괄 처리로 삭제하는 방법을 찾고 있습니다. 따라서 처음 1000 개를 삭제하고 삭제할 수 있습니다.

현재이 폴더에는 수십만 개의 파일이 있으며 실제로 통과 할 수 없습니다. 대신 모든 파일을 통해 반복하고 목록에서 삭제 표시된 파일을 저장하고 당신이 그들을 발견하면 바로 파이프를 다시 목록에 각 파일을 통해 다음 명령에 각 파일을 루핑의

Param(
    [Parameter(Mandatory=$true)][string]$Path, 
    [Parameter(Mandatory=$true)][string]$DaysToDelete 
) 

$limit = (Get-Date).AddDays($DaysToDelete) 
$LogFile = "FileCleanupLog-$(Get-Date -f yyyyMMdd_HH_mm_ss).txt"; 

function Log-Message 
{ 
    Param ([string]$logtext) 
    Add-content $LogFile -value $logtext 
} 

If (-Not (Test-Path $Path)) 
{ 
    Write-Host "Invalid Path provided!" -ForegroundColor Red 
    Exit 
} 

$files = Get-ChildItem -Path $Path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } 

If ($files.Count -GT 1) { 
    $files | % {$directory=$_.DirectoryName;(Log-Message "Deleting File $directory\$_");$_ } | Remove-Item -Force 
} 
+0

'get-childitem처럼 SELECT에 get-childitem을 파이핑 해 보셨습니까? | -first 100'을 선택 하시겠습니까? 현재 갖고있는 스크립트를 게시해야합니다. –

+0

너무 무례 해 줘서 고마워. 내 질문을 보면 일괄 적으로 파일을 삭제할 방법을 찾고 있다고 말했습니다. – TaylorN

+0

_이 작업을 수행 할 간단한 스크립트를 작성했습니다. 아마도 지금까지 시도한 것을 포함해야합니다. 지금 이것은 codez 질문에 대한 글씨처럼 읽습니다. 대부분의 경우 기존 코드를 수정하거나 개선하는 데 도움이됩니다. "일괄 처리"로 작업을 수행하더라도 작업을 사용하지 않는 한 한 번에 하나씩 수행 할 것입니다. 진행 상황 표시를 찾으십니까?그것을 실행시키고 그 일을하는 데있어서 해가되는 것은 무엇입니까? 자주 만만하면 첫 번째 패스 만 빨아들입니다. 최근에이 작업을 수행했지만 처음 실행하면 500 만 개의 파일이 삭제되었습니다. 이제 잘 돌아갑니다. – Matt

답변

2

.

그래서 대체 :

$files = Get-ChildItem -Path $Path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } 

If ($files.Count -GT 1) { 
    $files | % {$directory=$_.DirectoryName;(Log-Message "Deleting File $directory\$_");$_ } | Remove-Item -Force 
} 

을이 같은으로 :

Get-ChildItem -Path $Path -Recurse -Force ` 
| Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } ` 
| % { 
    $directory=$_.DirectoryName 
    (Log-Message "Deleting File $directory\$_") 
    $_ } ` 
| Remove-Item -Force 
+0

거대한 이득은 아니지만 왜'$ directory = $ _. DirectoryName' ...로 귀찮을 까? File $ ($ _. FullName) "' – Matt

+0

@Matt 왜 OP에 물어 봐야할까요? 'ForEach' 본문의 내용은 문제와 밀접한 연관성이 없으므로 기능적으로 동등합니다. –

+0

이것은 실제로 좋게 보입니다. 왜 내가 $ DirectoryName을 사용했는지, 아마도 늦은 밤을 확신 할 수 없다. 배치 작업은 더 빨리 만들 생각 이었지만, 이것이 효과가있을 것이라고 생각한다. – TaylorN

1

는 다음을 사용, 1000 일괄 적으로 파일을 삭제하는 기준을 충족하기 위해. select -first 1000은 while 루프를 돌 때마다 1000 개의 파일 만 삭제합니다.

while($true){ 
    $files = Get-ChildItem -Path $Path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | select -first 1000 
    If ($files.Count -GT 1) { 
     $files | % {$directory=$_.DirectoryName;(Log-Message "Deleting File $directory\$_");$_ } | Remove-Item -Force 
    } else { 
     exit 
    } 
} 

이 빨라집니다 경우 나도 몰라 - 그것은 의존는 처음 1000 개 파일을 찾거나하지 후 PowerShell을 얻을-ChildItem을 중지 똑똑합니다.

+0

그게 내가 생각하고 있었던거야. 배치 작업으로 인해 작업 속도가 빨라지는지 확실하지 않습니다. 내 경험에 비추어 볼 때 SQL/.NET 관점에서 볼 때 더 그렇습니다. – TaylorN

+1

'select '처럼 보이는 것은 3.0 [(documentation)] (https://technet.microsoft.com/en-us/library/hh849895.aspx) 현재 파이프 라인의 이전 명령을 단락시킬 것입니다 : * "Beginning Windows PowerShell 3.0에서 Select-Object에는 명령에서 사용되지 않는 개체를 만들고 처리하지 못하도록하는 최적화 기능이 있습니다. "* 여기서 한 가지 문제는 각 루프 내에서 Get-ChildItem 명령이 이전 루프마다 삭제되지 않은 모든 파일 –

+0

거친'$ true' /'exit' 조건 대신에'$ files.Count -GT 1' 로직을 루프의 종료 조건으로 쉽게 사용할 수 있습니다. 'do {#stuff} while ($ files.Count -gt 1)' – Matt

1

robocopy의 작동 방식을 약간 잘못 알았다는 것을 인정해야합니다. 파일을 삭제할 수는 있지만 복사 작업을 수행해야합니다. 따라서이 제안은 UNC 경로를 사용하지 않고 대상 컴퓨터에서 실행하는 것이 가장 좋습니다. 제 생각에는 여전히 실망 스럽지만 이것은 여전히 ​​실행 가능한 해결책이라고 생각합니다. 여기서 가장 중요한 것은 robocopy가 사후 처리없이 필요한 파일 만 선택한다는 것입니다.

$sourceDirectory = "D:\temp\New folder" 
$dummyDirectory = "D:\temp\trashbin" 
$loggingFile = "D:\temp\FileCleanupLog-$(Get-Date -f yyyyMMdd_HH_mm_ss).txt" 

# Build the dummy directory. It will be deleted in the end. 
New-Item -Path $dummyDirectory -ItemType Directory | Out-Null 

& robocopy.exe $sourceDirectory /njh /ndl /nc /njs /minage:$days /mov /e /ns /np /l | Set-Content $loggingFile 

# Purge the dummy directory with all the content we don't want 
Remove-Item -Path $dummyDirectory -Force -Confirm:$false -Recurse 

다음은 사용 된 모든 스위치의 의미입니다. 대부분은 로깅을 위해 출력을 정리합니다. 로그에는 제거 된 전체 경로 목록 만 있어야합니다. 이것은 현재 디렉토리 구조에 영향을 미치지 않습니다. 필요한 경우 스위치 변경으로이를 해결합니다. 또한 /l은 로깅에만 사용됩니다. 이 스위치를 사용하여 원하는 파일이 제거되는지 테스트 할 수 있습니다. 실제 생산 테스트를 수행하려면이를 제거해야합니다.

 
/minage:N  Specifies the minimum file age (exclude files newer than N days or date). 
/njh    Specifies that there is no job header. 
/njs    Specifies that there is no job summary. 
/l    Specifies that files are to be listed only (and not copied, deleted, or time stamped). 
/mov    Moves files, and deletes them from the source after they are copied. 
/ndl    Specifies that directory names are not to be logged. 
/nc    Specifies that file classes are not to be logged.\ 
/np    Specifies that the progress of the copying operation (the number of files or directories copied so far) will not be displayed. 

이렇게하면 화면에 데이터를 표시하는 데 시간을 소비하지 않을 경우 더 빨리 수행됩니다. 그래서 나는 구체적으로 /np을 넣었습니다.