如何复制文件然后将目标路径保存到 CSV

How to copy a file then save the destination path to CSV

我正在尝试将一批文件(文件名以 6 位数字开头的文件)从临时文件夹复制到永久位置,不包括新位置中已存在的文件。

复制完成后,我想将复制文件的文件名和新路径导出到 CSV 文件中。

获取旧文件位置并导出为 CSV 非常容易,我只是不太确定如何获取新文件位置。

我的脚本是这样的:

# Prompt for file origin
$file_location = Read-Host -Prompt "Where do you want your files to come from?"
# Prompt for file destination 
$file_destination = Read-Host -Prompt "Where do you want your files to go? `n(They won't be copied if they're already there)"

# Save contents of file destination - used to check for duplicates
$dest_contents = Get-ChildItem $file_destination

<# For all of the files of interest (those whose names begin with 6 digits) in $file_location, 
     determine whether that filename already exists in the target directory ($file_destination)
     If it doesn't, copy the file to the destination
     Then save the filename and the new** filepath to a CSV #>

Get-ChildItem -Path $file_location |      
    Where-Object { $_.Name -match '^\d{6}' -And !($dest_contents -Match $_.Name ) } |
    Copy-Item -Destination $file_destination -PassThru | 
    Select-Object -Property Name, FullName |             # **Note: This saves the old filepath, not the new one
    Export-CSV -Path "$file_location\files_copied.csv" -NoClobber

您可以通过对代码进行一些更改来完成此操作

# Prompt for file origin
$file_location = Read-Host -Prompt "Where do you want your files to come from?"
# Prompt for file destination 
$file_destination = Read-Host -Prompt "Where do you want your files to go? `n(They won't be copied if they're already there)"

# Save contents of file destination - used to check for duplicates
$dest_contents = Get-ChildItem $file_destination | Select-Object -ExpandProperty Name

<# For all of the files of interest (those whose names begin with 6 digits) in $file_location, 
     determine whether that filename already exists in the target directory ($file_destination)
     If it doesn't, copy the file to the destination
     Then save the filename and the new** filepath to a CSV #>

Get-ChildItem -Path $file_location |      
    Where-Object { $_.Name -match '^\d{6}' -and ($dest_contents -notcontains $_.Name ) } |
    ForEach-Object { 
        Copy-Item -Path $_.FullName -Destination $file_destination 
        # emit a PSObject storing the Name and (destination) FullName of the file that has been copied
        # This will be used to generate the output in the 'files_copied.csv'
        New-Object -TypeName PSObject -Property ([ordered]@{ Name = $_.Name; FullName = (Join-Path $file_destination $_.Name)})
    } | 
    Export-CSV -Path "$file_location\files_copied.csv" -NoTypeInformation -Force

请注意,我只收集目标路径中已有文件的 名称 ,而不是 fileInfo 对象。这使它变得很多 'leaner' 因为收集的唯一原因是要有一个文件名集合来比较。

就像现在一样,'files_copied.csv' 有一个固定的名称,我个人认为通过向其添加当前日期来使其更通用是个好主意,例如 [=17] =]

Export-CSV -Path ("{0}\files_copied_{1}.csv" -f $file_location, (Get-Date).ToString("yyyy-MM-dd")) -NoTypeInformation -Force 

P.s。我在这里使用 [ordered] 所以输出将始终具有相同顺序的属性。但是,这需要 PowerShell v3 或更高版本。 另外,如果您需要确保代码只复制文件而不复制目录,我建议查看 Get-ChildItem 命令上的 -File-Attributes 开关。如果您的 PowerShell 版本是 2.0,您可以使用 Where-Object { !$_.PSIsContainer } 构造仅过滤掉文件。

  • 我会使用不同的方法测试在迭代源文件时目标是否存在。

  • 要附加到当前的 csv(日志)文件,您需要删除新文件的 header。

  • 因为 Get-ChildItem 允许范围 [0-9] 你可以直接 select 前导数字

## Q:\Test18\SO_51738853.ps1
# Prompt for file origin
$SrcDir = Read-Host -Prompt "Where do you want your files to come from?"

# Prompt for file destination 
$DstDir = Read-Host -Prompt "Where do you want your files to go? `n(They won't be copied if they're already there)"

$SrcFiles = Join-Path (Get-Item $SrcDir).Fullname [0-9][0-9][0-9][0-9][0-9][0-9]*

$CopiedFiles = ForEach ($SrcFile in (Get-ChildItem -Path $SrcFiles)){
    $DstFile = Join-Path $DstDir $SrcFile.Name
    If (!(Test-Path $DstFile)){
        $SrcFile | Copy-Item  -Destination $DstFile -PassThru | 
            Select-Object -Property Name, FullName
    }
}    

# Check if log file exists, if yes append, otherwise export.
$LogFile = Join-Path $SrcDir "files_copied.csv"
If ($CopiedFiles){
    If (!(Test-Path $LogFile)){
        Export-CSV -Path $LogFile -InputObject $CopiedFiles -NoTypeInformation
    } else {
        # We need to remove the Header appending to the present csv
        $CopiedFiles | ConvertTo-Csv -NoType | Select-Object -Skip 1 | Add-Content -Path $LogFile
    }
}