Robocopy and get Copied file name

岁酱吖の 提交于 2020-01-17 07:11:53

问题


I'm using robocopy to only sync only newer file, but I also need to get the file name being copied.

I've to further use copied file name to make a entry in a some other file.

I wasn't able to found switch, which only displays copied file name, any powershell script of batch file will also be fine.


回答1:


This function parses all the RoboCopy text output and outputs that as a nice object.

Use it like this:

$RoboCopyOutput = robocopy $source $destination /ROBOSWITCHES

Parse-RoboCopyOutput $RoboCopyOutput

Or this:

Parse-RoboCopyOutput (robocopy e t /s)

(Which shows the error handling)

I can't claim all the ninja regex skills as my own: I found something on this online a few years ago and have expanded it over time. Sorry but I can't find the original article now, or I'd post a link to that.

My RoboCopy version check only looks for the versions that I encounter in my environment and is not exhaustive, so watch out for that. It should be easy enough to find out your version's date format and add it to the switch statement.

    Function Parse-RoboCopyOutput ($RoboCopyOutput)
{
    #Get RoboCopy version info to determine the date format
    switch ((Get-Command robocopy).FileVersionInfo.ProductVersion)
    {
        {$_ -eq 'XP027'}            {$RobocopyDateFormat = 'ddd MMM dd HH:mm:ss yyyy' ; break}  #Vista / Windows 7 / Server 2008
        {$_ -eq '6.2.9200.16384'}   {$RobocopyDateFormat = 'dd MMMM yyyy HH:mm:ss' ; break}     #Windows 8
        {$_ -eq '6.3.9600.16384'}   {$RobocopyDateFormat = 'dd MMMM yyyy HH:mm:ss' ; break}     #Windows 8.1
        default                     {throw "Unknown robocopy version."}
    }

    #Find the line numbers of the '----' spacers in the robocopy output
    $null,$HeaderStart,$HeaderEnd,$FooterStart = $RoboCopyOutput | Select-String  "----" | Foreach-Object {$_.linenumber}

    #Create the object to store all the parsed robocopy output information
    $RoboObject = New-Object PSObject

    #Grab the first section of the robocopy output by line number
    $RoboCopyOutput[$HeaderStart..$HeaderEnd] | Foreach-Object `
    {
        Switch -regex ($_)
        {
            'Started :(.*)'     {
                                    Add-Member -InputObject $RoboObject -Name StartTime -Value `
                                        ([datetime]::ParseExact($matches[1].trim(),$RobocopyDateFormat,$null)) -MemberType NoteProperty
                                }
            'Source :(.*)'      {
                                    Add-Member -InputObject $RoboObject -Name Source -Value ($matches[1].trim()) -MemberType NoteProperty
                                }
            'Dest (.)(.*)'      {
                                    Add-Member -InputObject $RoboObject -Name Destination -Value ($matches[2].trim()) -MemberType NoteProperty
                                }
            '^    Files :(.*)'  {
                                    Add-Member -InputObject $RoboObject -Name FilesToCopy -Value ($matches[1].trim()) -MemberType NoteProperty
                                }
            'Exc Files :(.*)'   {
                                    Add-Member -InputObject $RoboObject -Name ExcFiles -Value ($matches[1].trim()) -MemberType NoteProperty
                                }
            'Exc Dirs :(.*)'    {
                                    Add-Member -InputObject $RoboObject -Name ExcDirs -Value ($matches[1].trim()) -MemberType NoteProperty
                                }
            'Options :(.*)'     {
                                    Add-Member -InputObject $RoboObject -Name Options -Value ($matches[1].trim()) -MemberType NoteProperty
                                }
        }
    }

    #Grab the second section of the robocopy output by line number (if the copy has completed).
    if ($FooterStart)
    {
        $RoboCopyOutput[$FooterStart..($RoboCopyOutput.Count -1)] | Foreach-Object `
        {
            Switch -regex ($_)
            {
                'Ended :(.*)'       {
                                        Add-Member -InputObject $RoboObject -Name StopTime `
                                            -Value ([datetime]::ParseExact($matches[1].trim(),$RobocopyDateFormat,$null)) -MemberType NoteProperty
                                    }
                'Speed :(.*) Bytes' {
                                        Add-Member -InputObject $RoboObject -Name BytesPerSecond -Value ($matches[1].trim()) -MemberType NoteProperty
                                    }
                '(Total.*)'         {
                                        $Columns = $_.Split() | Where-Object {$_}
                                    }
                'Dirs :(.*)'        {
                                        $Fields = $matches[1].Split() | Where-Object {$_}

                                        $Dirs = New-Object PSObject

                                        0..5 | Foreach-Object `
                                        {
                                            Add-Member -InputObject $Dirs -Name $Columns[$_] -Value $Fields[$_] -MemberType NoteProperty

                                            Add-Member -InputObject $Dirs -Name 'toString' -MemberType ScriptMethod `
                                                -Value {[string]::Join(" ",($this.psobject.Properties | Foreach-Object {"$($_.name):$($_.value)"}))} -force
                                        }

                                        Add-Member -InputObject $RoboObject -Name Directories -Value $Dirs -MemberType NoteProperty
                                    }
                'Files :(.*)'       {
                                        $Fields = $matches[1].Split() | Where-Object {$_}

                                        $Files = New-Object PSObject

                                        0..5 | Foreach-Object `
                                        {
                                            Add-Member -InputObject $Files -Name $Columns[$_] -Value $Fields[$_] -MemberType NoteProperty

                                            Add-Member -InputObject $Files -Name 'toString' -MemberType ScriptMethod `
                                                -Value {[string]::Join(" ",($this.psobject.Properties | Foreach-Object {"$($_.name):$($_.value)"}))} -force
                                        }

                                        Add-Member -InputObject $RoboObject -Name Files -Value $files -MemberType NoteProperty
                                    }
                'Bytes :(.*)'       {
                                        $Fields = $matches[1].Split() | Where-Object {$_}

                                        $Fields = $Fields | Foreach-Object {$New=@();$i=0}{if ($_ -match '\d') {$New += $_;$i++} else {$New[$i-1] = ([double]$New[$i-1]) * "1${_}B"}}{$New}

                                        $Bytes = New-Object PSObject

                                        0..5 | Foreach-Object `
                                        {
                                            Add-Member -InputObject $Bytes -Name $Columns[$_] -Value $Fields[$_] -MemberType NoteProperty

                                            Add-Member -InputObject $Bytes -Name 'toString' -MemberType ScriptMethod `
                                                -Value {
                                                    [string]::Join(" ",($this.psobject.Properties | Foreach-Object {"$($_.name):$($_.value)"}))
                                                    } -force
                                        }

                                        Add-Member -InputObject $RoboObject -Name Bytes -Value $bytes -MemberType NoteProperty
                                    }
                }
            }

        #If the copy completed, calculate elapsed time
        if ($RoboObject.StopTime)
        {
            $ElapsedTime = ($RoboObject.StopTime) - ($RoboObject.StartTime)

            Add-Member -InputObject $RoboObject -Name ElapsedTime -Value $ElapsedTime -MemberType NoteProperty
        }
    }
    else
    {
        #Grab the RoboCopy error
        $RoboCopyOutput[($HeaderEnd +1)..($RoboCopyOutput.Count -1)] | ForEach-Object `
        {           
            $ErrorMessage += $_.ToString()          
        }

        Add-Member -InputObject $RoboObject -Name ErrorMessage -Value $ErrorMessage -MemberType NoteProperty
    }

    #Output
    $RoboObject
}



回答2:


user182904,

I have revised my answer to suit your requirements.

Try the following cmd file.

1) It will create a log file from robocopy with just folders\files copied.

2) It will then strip that log file to just the files copied.

@echo off

rem source folders for robocopy
set source="c:\test\files"
set destin="c:\test\files2"

rem logfile names
set sourcelogfile=log-from-robocopy.txt
set destinlogfile=log-just-files.txt

rem robocopy command to output files copied
robocopy %source%  %destin% /e  /LOG:"%sourcelogfile%" /NP /NS /NC /NDL /TEE /NJH /NJS

rem for loop through robocopy output and stip it down to just file names into new logfile
for /f "tokens=*" %%i in (%sourcelogfile%) do (
    for /f "delims=" %%f in ("%%i") do (
        echo %%~nxf >> %destinlogfile%
    )
)

rem end of code

You can add your options to the Robocopy line, but you will need the options added at the end of that line, to output a log file that the rest of the script will parse.

Hope that helps.

Details of all the robocopy switches can be found here:

source: http://ss64.com/nt/robocopy.html



来源:https://stackoverflow.com/questions/28423888/robocopy-and-get-copied-file-name

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!