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

时间:2018-08-08 04:53:29

标签: powershell powershell-v2.0 export-to-csv

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

复制完成后,我想将文件名和复制文件的新路径导出到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

2 个答案:

答案 0 :(得分:1)

您可以对代码进行一些更改

# 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对象。这使它变得“精简”得多,因为收集的唯一原因是要收集要比较的文件名。

现在,您已经为“ files_copied.csv”使用了固定的名称,我个人认为,通过在其上添加当前日期(例如)来使其更通用,是一个好主意

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

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

答案 1 :(得分:0)

  • 我将使用另一种方法测试迭代源文件时是否存在目标。

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

  • 由于Get-ChildItem允许范围[0-9],因此您可以直接选择前导数字

## Q:\Test\2018\08\08\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
    }
}