![获取子项 | 复制项](https://linux22.com/image/763951/%E8%8E%B7%E5%8F%96%E5%AD%90%E9%A1%B9%20%7C%20%E5%A4%8D%E5%88%B6%E9%A1%B9.png)
尝试解释为什么copy-item
ps 脚本无法按预期工作。我尝试在我的文件服务器中搜索所有附加/有效驱动器上的任何 *.pst 文件,然后将找到的 .pst 文件复制到其他共享位置。下面的脚本没有给我预期的结果。显示Out-File
未找到 .pst 文件。当我检查目标文件夹时,我发现只有一个 *.pst 文件被复制过来。我已经验证了文件服务器上的不同目录和子文件夹中有多个文件。$Computers.txt 文件未列出找到或复制的任何 .pst 文件
截屏
以下是我的新手 ps 脚本
$Computers = hostname
get-psdrive -PSProvider "FileSystem" `
| foreach {Write-Output $Computers $_.Root;get-childitem $_.Root -include *.PST -Recurse -erroraction silentlyContinue | Copy-Item -Destination "\\Server1\PSTsbackupfolder\" `
| Select-Object -Property $Computers,Directory,Name} | Format-Table -AutoSize `
| Out-File -FilePath "\\Server1\Results\$Computers.txt"
如果我| Copy-Item -Destination "\\Server1\PSTsbackupfolder\"
从脚本中删除,输出文件 $Computers.txt 将显示预期结果,但复制这些 .pst 文件的目标仍然是必要的。$Computers.txt 的输出文件结果如下:
截屏, 任何建议都值得感激。
答案1
您需要添加-Append
以Out-File
获取整个列表;每次遍历列表时都会创建一个新文件。
Copy-Item
如果从管道中删除,则会将 的输出发送Get-ChildItem
到管道的其余部分。如果保留Copy-Item
在那里,则会发送 的输出Copy-Item
,这只是它刚刚处理的一个文件。
如果您尝试将 ServerA 上找到的所有文件复制到\\server1\PSTBackupFolder
,则最好在 ServerA 上运行 Robocopy,如下所示:
Get-PSDrive -PSProvider FileSystem | ForEach-Objecct {robocopy $_.root *.pst /z /v /r:5 /log:\\Server1\PSTsbackupfolder\RoboCopy.$($_.Name).log \\Server1\PSTsbackupfolder}
这将获取所有,然后遍历与 匹配的FileSystem
PSDrives
每个驱动器和robocopy
位于根目录(驱动器号)下的所有文件。我们以可恢复模式()详细复制它们(),重试复制 5 次(),并将所有事务记录到*.pst
\\Server1\PSTBackupfolder
/z
/v
/r:5
\\server1\pstbackupfolder\robocopy.DRIVELETTER.Log
我们使用内联替换 ( $($_.Name)
) 将复制日志拆分为单独的文件,因为当您试图弄清楚为什么 Bill 的 PST 没有从 L: 驱动器复制时,如果您只需要查看 50 个条目而不是 50,000 个条目,那么处理起来会容易得多
答案2
我确信有更好、更干净、更有效的方法来编写此代码,我将采纳您的建议并尝试改进我的代码,但当前技能水平- 这就是我能够拼凑起来的,它给了我我想要的最终结果。
$FileServer = hostname
$DestPath = "c:\PSTs\$FileServer"
#Checks if the Destination Dir/Path exists, if not it creates the folder and names it whatever the hostname is
If ((Test-Path -path $DestPath -PathType Container) -eq $false) {New-Item $DestPath -ItemType Directory}
#Searches for .psts files on host, exports results to .csv file.
Get-psdrive -PSProvider "FileSystem" `
| ForEach-Object {(get-childitem $_.Root -recurse -file -Filter *.PST -erroraction silentlyContinue `
| Select-Object -Property Directory,Name)} | Export-Csv -path "$DestPath\$FileServer.csv" -NoTypeInformation -Force
#Sets variable for .CSV file from previous command
$PstPath = Get-Content -Path "$DestPath\$FileServer.csv"
#Modifying .CSV for preceding commands to work.
$PSTsCSV = "$DestPath\$FileServer.csv"
($PstPath).Replace('"Directory",','"Path"').replace('"Name"','').replace('","','\') | Out-File -FilePath $PSTsCSV -force
#Reads each line of .CSV file, copies .pst file from source to destination, if file name exsists...
#in destination, it will re-name file appending a consecutive number
$CSV = Import-Csv $DestPath\$FileServer.csv
Get-ChildItem -Path $CSV.Path | ForEach-Object {
$num=1
$newName = Join-Path -Path $DestPath -ChildPath $_.Name
while(Test-Path -Path $newName)
{
$newName = Join-Path $DestPath ($_.BaseName + "_$num" + $_.Extension)
$num+=1
}
$_ | Copy-Item -Destination $newName
}
我在我的脚本中发现了一个问题,这是有问题的行。
($PstPath).Replace('"Directory",','"Path"').replace('"Name"','').replace('","','\') | Out-File -FilePath $PSTsCSV -force
如果在服务器上搜索 .psts,结果为不.pst 文件,则 .csv 文件的输出将没有结果。将出现错误,指出您不能对空值表达式调用方法。
You cannot call a method on a null-valued expression.
At D:\Scripts\PowerShell\tempCodeRunnerFile.ps1:6 char:1
+ ($PstPath).Replace('"Directory",','"Path"').replace('"Name"','').repl ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
为了补救(我所能想到的最好的办法),如果找不到 .pst 文件,我会重写代码,添加以下内容,-ErrorAction Stop
这样脚本就会在此时停止,就像这样
Get-Content $PSTsCSV.Replace('"Directory",','"Path"').replace('"Name"','').replace('","','\') -ErrorAction Stop | Out-File -FilePath $PSTsCSV -force