Powershell - 努力从可变位置复制文件

Powershell - Struggling to copy file from variable location

我一直在用 powershell 脚本敲我的脑袋,我已经尝试了几种不同的方法,想知道是否有人可以提供帮助?

目前不确定我是否只是在做一些愚蠢的事情,在此先感谢

目标:

要将 vbs 文件从用户的家庭驱动器复制到不同的位置,vbs 文件的位置会根据需要帐户管理员的用户进行更改,因此这需要可变。它从一个文本文件中获取位置,该文​​件包括要到达的确切路径和已经创建的用于将文件复制到的目标。

我目前遇到的问题:

$location = Get-Content C:\Users\Administrator\Desktop\here\drive4.txt | Out-String
$dest = "C:\Users\Administrator\Desktop\here"
Get-ChildItem -Path $location | 
Copy-Item -Destination $dest -Recurse -Container -filter "peruser.vbs"
write-host $location

Read-Host -Prompt "Press Enter to continue or CTRL+C to quit"

问题

请看下面,我已经写主机来显示 powershell 试图到达的位置,作为旁注,我可以通过文件资源管理器很好地到达这个位置

Screenshot of error

收到错误

Get-ChildItem : Illegal characters in path.
At C:\Users\Administrator\Desktop\MapNetworkDrives2.ps1:17 char:1
+ Get-ChildItem -Path $location | Copy-Item -Destination $dest -Recurse -Container ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (\WIN-7V7GI0R7C...             
:String) [Get-ChildItem], ArgumentException
    + FullyQualifiedErrorId : ItemExistsArgumentError,Microsoft.PowerShell.Commands.GetChildItemCommand

Get-ChildItem : Cannot find path '\WIN-7V7GI0R7CFK\homedrives\Onetest$                                                     

' because it does not exist.
At C:\Users\Administrator\Desktop\MapNetworkDrives2.ps1:17 char:1
+ Get-ChildItem -Path $location | Copy-Item -Destination $dest -Recurse -Container ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (\WIN-7V7GI0R7C...             
:String) [Get-ChildItem], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand

除非我误解了你 - 你只是想根据列表将文件复制到不同的位置。如果是这样,您只需要遍历列表即可。这对你有用吗?

$location = Get-Content "C:\Users\Administrator\Desktop\here\drive4.txt"
$dest = "C:\Users\Administrator\Desktop\here"

foreach ($loc in $location){
    $vbs = (gci $loc -Filter "peruser.vbs").FullName
    Copy-Item $vbs $dest -Force
}

你没有显示文本文件中的内容,迫使我们猜测,相对于试图帮助你而言,这并不是一件好事。所以,我假设它只是一个驱动器号或路径 UNC 的列表,这真的没有实际意义,因为你可以动态地提取它们,因此不需要文件。

我不明白你为什么要这样做...

Get-Content 'C:\Users\Administrator\Desktop\here\drive4.txt' | 
Out-String

如果它只是一个供阅读的文本文件,你为什么要把它传送到任何地方?

你不需要双引号。单引号用于简单字符串,双引号用于变量扩展或其他特定格式要求

$dest = 'C:\Users\Adminstrator\Desktop\here'

直接传读就可以了

Get-Content 'C:\Users\Administrator\Desktop\here\drive4.txt' | 
ForEach {
    "Processing location $($PSItem.FullName)"
    Copy-Item -Path $PSItem.FullName -Destination $dest -Filter 'peruser.vbs' -Recurse -WhatIf
} 

注意事项: 您不需要 Write-Host 来输出到屏幕,因为这是 PowerShell 的默认设置,我将在后面的示例中展示。真的,除了用颜色写屏幕文字,你根本不需要用Write-Host/echo,好吧,还有一些特定的时间用它。

另外请注意,regarding Write-Host from the inventor of Monad/PowerShell Jeffery Snover

您也不一定需要 Get-ChildItem 和 Copy-Item,因为两者都会递归地读取文件夹树。 正如我将在下面展示的那样。我正在使用 splatting 来收紧代码块以提高可读性。

因此,如果我仅使用系统上的驱动器和文件夹进行演示。逐步完成脚本构建,以确保在进入下一步之前我在每一步都得到了我期望的结果。

Get-PSDrive -PSProvider FileSystem | 
Format-Table -AutoSize
<#
# Results

Name Used (GB) Free (GB) Provider   Root  CurrentLocation
---- --------- --------- --------   ----  ---------------
C       357.48    118.83 FileSystem C:\  Windows\system32
D       114.10    362.71 FileSystem D:\           Scripts
E      1194.00    668.89 FileSystem E:\                  
F      3537.07    188.83 FileSystem F:\                  
G                        FileSystem G:\  
#>

# Validate if there is any content in the destination
Try 
{
    Get-PSDrive -PSProvider FileSystem | 
    Where Name -eq 'D' | 
    ForEach {
        "Processing location $($PSItem.Root) and the contents are as listed."
        (Get-ChildItem -Path 'D:\Temp\here' -Recurse).FullName
    }
}
Catch {Write-Warning -Message 'No content in the destination folder'}
<#
# Results

Processing location D:\ and the contents are as listed.
WARNING: No content in the destination folder
#>

# Show what is on the drive for the source files
Get-PSDrive -PSProvider FileSystem | 
Where Name -eq 'D' | 
ForEach{
    "Processing the location $($PSItem.Root)"
    (Get-ChildItem -Path "$($PSItem.Root)\Temp\book1.csv" -Recurse).FullName
}
<#
# Results

Processing the location D:\
D:\Temp\Source\book1.csv
D:\Temp\book1.csv
#>

<#
# Show what will happen if a Copy files from the source to the destination occurs
Using splatting for readability
#>

Get-PSDrive -PSProvider FileSystem | 
Where Name -eq 'D' | 
ForEach{
    "Processing the location $($PSItem.Root)"
    $CopyItemSplat = @{
        Path        = "$($PSItem.Root)\Temp\book1.csv"  
        Destination = "$($PSItem.Root)\Temp\here" 
        Recurse     = $true
        WhatIf      = $true
    }
}
Copy-Item @CopyItemSplat
<#
# Results

Processing the location D:\
What if: Performing the operation "Copy File" on target "Item: D:\Temp\book1.csv Destination: D:\Temp\here\book1.csv".

If the results are as expected, execute the action
Using splatting for readability
#>

Get-PSDrive -PSProvider FileSystem | 
Where Name -eq 'D' | 
ForEach{
    "Processing the location $($PSItem.Root)"
    $CopyItemSplat = @{
        Path        = "$($PSItem.Root)\Temp\book1.csv"  
        Destination = "$($PSItem.Root)\Temp\here" 
        Recurse     = $true
    }
}
Copy-Item @CopyItemSplat
<#
# Results

Processing the location D:\
#>

# Validate if there is any content in the destination
Try 
{
    Get-PSDrive -PSProvider FileSystem | 
    Where Name -eq 'D' | 
    ForEach {
        "Processing location $($PSItem.Root) and the contents are as listed."
        (Get-ChildItem -Path 'D:\Temp\here' -Recurse).FullName
    }
}
Catch {Write-Warning -Message 'No content in the destination folder'}
<#
# Results

Processing location D:\ and the contents are as listed.
D:\Temp\here\book1.csv
#>