2011-10-25 6 views
5

यहां परिदृश्य है: हमारे पास एक उत्पादन वेब सर्वर है जिसमें कुछ हज़ार फाइलें और फ़ोल्डर्स हैं जिनके पास "_DATE" संलग्न है। हम उन्हें एक अस्थायी फ़ोल्डर में ले जाना चाहते हैं (सुनिश्चित करें कि वे उपयोग में नहीं हैं), और बाद की तारीख में फ़ाइलों को हटा दें।पावरशेल: रेगेक्स वैल्यू के आधार पर फ़ाइलों को कॉपी/ले जाएं, फ़ोल्डर संरचना को बनाए रखना,

मैं उपयोग कर सकते हैं:

Get-ChildItem -Path W:\IIS -Recurse | Where-Object{$_.Name -match "_\d{8,10}$"} 

सभी फ़ाइलें/फ़ोल्डर और उनके स्थानों की एक सूची प्राप्त करने के लिए। लेकिन उन्हें मैन्युअल रूप से हटाने से बहुत सारे काम की तरह लगता है, खासकर यदि भविष्य में इसकी आवश्यकता है।

cls 

$source = "W:\IIS" 
$destination = "C:\Temp\DevTest" 

foreach ($i in Get-ChildItem -Path $source -Recurse) 
{ 
    if ($i.Name -match "_\d{8,10}$") 
    { 
     Copy-Item -Path $i.FullName -Destination $item.FullName.ToString().Replace($source,$destination).Trim($item.Name) 
    } 
} 

और:: मैं कुछ उदाहरण है कि लगभग मैं क्या चाहते हो पाया है

cls 

$source = "W:\IIS" 
$destination = "C:\Temp\DevTest" 

$bin = Get-ChildItem -Path $source -Recurse | Where-Object{$_.Name -match "_\d{8,10}$"} 

foreach ($item in $bin) { 
    Copy-Item -Path $item.FullName -Container -Destination $item.FullName.ToString().Replace($source,$destination).Trim($item.Name) -Recurse 
} 

इन दोनों के साथ मुद्दा यह है कि जब मैं उन्हें सिर्फ कॉपी-आइटम के साथ परीक्षण मैं एक साथ खत्म कर रहे हैं फ्लैट निर्देशिका, और मुझे निर्देशिका संरचना को संरक्षित करने की आवश्यकता है ताकि यदि चाल गलत हो जाए तो मैं वापस कर सकता हूं (अधिमानतः सभी फ़ोल्डरों को आईआईएस फ़ोल्डर में खींचकर छोड़कर) या मुझे कई अतिरिक्त फ़ोल्डरों/फ़ाइलों की एक प्रति प्राप्त होती है जब मैं पहली कमांड चलाता हूं तो प्रकट न करें।

का मेरा पहला आदेश में संशोधन:

Get-ChildItem -Path W:\IIS -Recurse | Where-Object{$_.Name -match "_\d{8,10}$"} | Copy-Item -Container -Destination C:\Temp\DevTest -Recurse 

सब कुछ मैं जरूरत है कॉपी करेंगे, लेकिन एक फ्लैट निर्देशिका वृक्ष के साथ, बजाय वृक्ष संरचना को बनाए रखना है (लेकिन गंतव्य के साथ स्रोत निर्देशिका प्रतिस्थापन)।

कोई सुझाव/टिप्पणियां?

उत्तर

1

आप निम्नलिखित के साथ खेल सकते हैं, जो काम पूरा करने लगता है (हालांकि यह कुछ रिफैक्टरिंग का उपयोग कर सकता है)। कोर ProcessFolder(…) है जिसे रिकर्सिवली कहा जाता है।

function Log 
{ 
    param($Error) 
    if(!$script:log) 
    { 
     $script:log = join-path $dst "log$timestamp.txt" 
    } 
    $timestamp 
    $timestamp >> $script:log 
    $Error 
    $Error >> $script:log 
} 

function CopyFile 
{ 
    param($Path) 
    $tmp = join-path $dst $Path.Substring($src.Length) 
    write-host "File src: $Path" 
    write-host "File dst: $tmp" 
    Try 
    { 
     #copy the file 
     copy $Path $tmp -Force 
    } 
    Catch 
    { 
     Log "ERROR copying file $Path to $tmp`:` 
     $_" 
    } 
} 

function ProcessFolder 
{ 
    param($Path) 
    $tmp = join-path $dst $Path.Substring($src.Length) 
    write-host "Dir. src: $Path" 
    write-host "Dir. dst: $tmp" 
    Try 
    { 
     #create target directory 
     New-Item $tmp -itemtype directory -force > $null 
     #process files if they match 
     dir $Path | ?{!$_.PsIsContainer -and $_.Name -match "_\d{8,10}$" } | sort | %{ CopyFile $_.FullName } 
     #process subdirectories 
     dir $Path | ?{$_.PsIsContainer} | sort | %{ ProcessFolder $_.FullName } 
     #remove target directory if it contains no files on any level 
     if(!(dir $tmp -recurse | ?{!$_.PsIsContainer})) { del $tmp -recurse } 
    } 
    Catch 
    { 
     Log "ERROR copying folder $Path to $tmp`:` 
     $_" 
    } 
} 

cls 

$src = "W:\IIS\" 
$dst = "C:\Temp\DevTest\" 
$log = $null 
$timestamp = '{0:yyyyMMddHHmmssfffffff}' -f (Get-Date) 
ProcessFolder $src 

'' 
'DONE!' 
if($log) 
{ 
    echo "Check the log file: $log" 
} 
Read-Host 
+0

आह, मैंने नहीं देखा [manojlds का उत्तर] (http://stackoverflow.com/questions/7893919/powershell-copy-move-files-based-on-a-regex-value-retaining-the-folder -स्ट्रक्चर/7895211 # 7895211) अभी तक:] – mousio

2

पहला व्यक्ति आदर्श रूप से काम करना चाहिए। यह निर्देशिका संरचना को संरक्षित करता है। लेकिन आपको फ़ोल्डरों की प्रतिलिपि बनाने के बारे में सावधान रहना होगा। आप पैटर्न में बस फ़ाइलों को में चाहते हैं मान लिया जाये और आप परवाह नहीं है फ़ोल्डरों वहाँ होने के बारे में, आप नीचे कर सकते हैं:

$source = "W:\IIS" 
$destination = "C:\Temp\DevTest" 

if(-not (Test-Path $destination)) { mkdir $destination | out-null} 

foreach ($i in Get-ChildItem -Path $source -Recurse) 
{ 
    if (($i.Name -notmatch "_\d{8,10}$") -and (-not $i.PsIsContainer)) 
    { 
     continue; 
    } 
    Copy-Item -Path $i.FullName -Destination $i.FullName.Replace($source,$destination).Trim($i.Name) 
} 
+0

+1 ठीक है आपका कोड (एक स्पष्टीकरण) मेरा से स्पष्ट है, लेकिन मैंने इसे एक टेबल के कोने पर बनाया है। – JPBlanc

+0

@ 666jfox777 - क्या मतलब है रेगेक्स नहीं उठाया? – manojlds

+0

@manojlds यह लगभग हर फ़ोल्डर की प्रतिलिपि बना रहा है न कि मैं बाद में था और मैं कई अतिरिक्त खाली निर्देशिकाओं के साथ समाप्त हुआ जो regex (_ \ d {8,10} $) से मेल नहीं खाते हैं। – 666jfox777

1

मुझे Copy-Item के लिए एक मेस आप पढ़ सकते हैं अन्य StackOverflow उत्तर देता this one या this other one। यहां एक समाधान है जो एक प्रकार का 'ब्रिकॉलेज' है।

$source = "W:\\IIS" # Really double \ 

Get-ChildItem -Path $source -Recurse | Where-Object{($_.Name -match ""_\d{8,10}$") -or ($_.psiscontainer)} | % {copy-item $_.fullname ($_.fullname -replace $source,'C:\Temp\DevTest') } 
संबंधित मुद्दे