Hi Everyone,

my script below:

  1. try to copy files from local folder C: drive to F Drive example.

need to check if the file in destination F Drive exist, if not just copy and log to say it has succesfully copied or the file already exist in destination folder.

I had to choose one three files from a folder example. abc.txt, abc2.txt and xyz.pdf out of number of files from a folder

Here is my script, just struggling to use array to list the above three files to put in an array.

#Copy only new files, saves time by only copying items that don't exist on the destination.

#Gets all of the files from the source directory

$FilesInSource = gci -File -path "\\xyzserver\ftp" | select -ExpandProperty Name

#Gets all of the files from destination folder
$FilesInDest = gci -File -Path "F:\ftp" | select -ExpandProperty name

#list the differences between the source and destination.
Compare-Object -DifferenceObject $FilesInSource -ReferenceObject $FilesInDest

#Loop through each album in the library
foreach ($filetocheck in $FilesInSource)
{
    #Check to see if desitnation directory contains file from the FilesInSource library
    if ($FilesInDest -notcontains $filetocheck)
{
    #If the files doesn't exist on the destination directory, copy it from source to destination folder
    write-host "$files is not on destination, copying to destination" -ForegroundColor Cyan
    Copy-Item -path "\\xyzserver\ftp\$filetocheck" -Destination "f:\ftp\$filetocheck"
}
}
6 Spice ups

This line below references a variable called $files that is not defined.

Copy-Item -path "C:\ftp\$file" -Destination "e:\ftp\$files"

Sorry for my limited knowledge, thanks for the correction, i just updated the source path and destination path.

When you use -Directory on Get-ChildItem, the command will only return directories rather than files. If you want only files, then use -File instead of -Directory.

Many thanks,

I replaced the -Directory to -File in original post and also used non-reserved variable in for loop ($filetocheck instead of $file)

  1. Now the only thing left is to log the outcome of which file is copied in log.txt file

  2. An array to specify the files I want to copy ${abc.txt, abc2.txt, abc.pdf} instead of copy all the files from source to destination.

$FilesInSource = gci -File -path "\\xyzserver\ftp" | select -ExpandProperty Name

#Gets all of the files from destination folder
$FilesInDest = gci -File -Path "F:\ftp" | select -ExpandProperty name

I always prefer using the right tool for the job and while PowerShell is able to copy files, I always prefer to use robocopy. You can also use PowerShell to evaluate the exit code to see if there where errors.

$Process = Start-Process -FilePath "C:\Windows\system32\Robocopy.exe" -ArgumentList "D:\SOURCE E:\DESTINATION /MIR /FFT /Z /DCOPY:DAT /W:5 /R:5 /MT:128" -PassThru -NoNewWindow -Wait
if ($Process.ExitCode -ge 8) {
	Write-Log -String "Error(s) Detected with Robocopy"
}

Here’s an explanation of all the exit codes

    if %ERRORLEVEL% EQU 16 echo ***FATAL ERROR*** & goto end
    if %ERRORLEVEL% EQU 15 echo OKCOPY + FAIL + MISMATCHES + XTRA & goto end
    if %ERRORLEVEL% EQU 14 echo FAIL + MISMATCHES + XTRA & goto end
    if %ERRORLEVEL% EQU 13 echo OKCOPY + FAIL + MISMATCHES & goto end
    if %ERRORLEVEL% EQU 12 echo FAIL + MISMATCHES& goto end
    if %ERRORLEVEL% EQU 11 echo OKCOPY + FAIL + XTRA & goto end
    if %ERRORLEVEL% EQU 10 echo FAIL + XTRA & goto end
    if %ERRORLEVEL% EQU 9 echo OKCOPY + FAIL & goto end
    if %ERRORLEVEL% EQU 8 echo FAIL & goto end
    if %ERRORLEVEL% EQU 7 echo OKCOPY + MISMATCHES + XTRA & goto end
    if %ERRORLEVEL% EQU 6 echo MISMATCHES + XTRA & goto end
    if %ERRORLEVEL% EQU 5 echo OKCOPY + MISMATCHES & goto end
    if %ERRORLEVEL% EQU 4 echo MISMATCHES & goto end
    if %ERRORLEVEL% EQU 3 echo OKCOPY + XTRA & goto end
    if %ERRORLEVEL% EQU 2 echo XTRA & goto end
    if %ERRORLEVEL% EQU 1 echo OKCOPY & goto end
    if %ERRORLEVEL% EQU 0 echo No Change & goto end
    :end  

https://ss64.com/nt/robocopy-exit.html

1 Spice up

Many thanks,

Robocopy is quite simple and robust for copying files, and I do believe in that, the only issues are

  1. need an array of hardcoded files to be compared and copied if doesnt exist.

eg. abc.txt, abc2.txt, text.log

  1. than log the outcome in a log.txt file.

I manage to use try within powershell to capture the error and append to the log.txt file, please see below and advise.

#Copy only new files, saves time by only copying items that don't exist on the destination.

#Gets all of the files from the source directory

$FilesInSource = gci -File -path "\\xyzserver\ftp" | select -ExpandProperty Name

#Gets all of the files from destination folder
$FilesInDest = gci -File -Path "F:\ftp" | select -ExpandProperty name

#list the differences between the source and destination.
Compare-Object -DifferenceObject $FilesInSource -ReferenceObject $FilesInDest

#Loop through files in the source library
foreach ($filetocheck in $FilesInSource)
{
    #Check to see if desitnation directory contains file from the FilesInSource library
    if ($FilesInDest -notcontains $filetocheck)
{
 

try{
    #If the files doesn't exist on the destination directory, copy it from source to destination folder
    write-host "$files is not on destination, copying to destination" -ForegroundColor Cyan
    Copy-Item -path "\\xyzserver\ftp\$filetocheck" -Destination "f:\ftp\$filetocheck"

    # if the script gets to this part, Copy-Item did not error
    echo "Date: $((Get-Date).ToString()). Status: Successfully copied" | out-file -append $logProgress
}catch{
    # what to do if an error is encountered:
    $ErrorMessage = $Error[0].Exception.Message
    echo "Date: $((Get-Date).ToString()). Status: Copy Failure - $ErrorMessage" | out-file -append $logProgress
	}
}

}
}

What is not working? Your Write-Host command contains that $files variable again, which has no value assigned to it.

Thanks, variable updated.

The only issue i have is the for loop had to check only hard coded files instead of all files in a source and destination copy

i.e,

$filestocopy{abc.txt,abc2.txt,log.txt}

#Loop through files in the source library at first than compare if they exist in destination,

#if not copy

Hope i made it clear.

example.

# Full path of the file
$file = '\\server\ftp\abc.txt'
$file2 = '\\server\ftp\abc2.txt'
$file3 = '\\server\ftp\log.txt'

#If the file does not exist, copy it.

It sounds like you just want to query your source directory for a specific list of files. Then check if those names exist in the destination.

$FilesToFind = 'abc.txt','abc2.txt','xyz.pdf'
$FilesInSource = gci -File -path "\\xyzserver\ftp" |
    where Name -in $FilesToFind | select -ExpandProperty Name
$FilesInDest = gci -File -Path "F:\ftp" |
    where Name -in $FilesToFind | select -ExpandProperty name

The problem with this is that you could have files of the same name but have different contents. This is why robocopy is superior.

They are not the same name, different names abc.txt, abc2.txt and log.pdf

I am nearly their.

$folder = '\\server\ftp'
    $files = @(
        "abc.txt",
        "abc2.txt"
    )
    Write-Host "Folder: $folder."
    # Get only files and only their names
    $folderFiles = Get-ChildItem -Path $folder -File -Name
    foreach ($f in $files) {
        if ($folderFiles -contains $f) { 
            Write-Host "File $f was found." -foregroundcolor green
        } else { 
            Write-Host "File $f was not found!" -foregroundcolor red 
        }
    }

When I say “files of the same name,” I mean file abc.txt in the source and abc.txt in the destination. But they both contain different contents inside of the files.

I agree, the need is to check those files exists first in source directory,

if exists,

check the destination folder contains the same file,

if the file exist in destination.

dont copy, just append the log

if doesn’t exist

copy to destination and append the log.

That’s what i am trying to achieve.

$Source_folder = '\\server\ftp'
$Destination_folder = 'f:\ftp'

    $files = @(
        "abc.txt",
        "abc2.txt"
    )
    Write-Host "Folder: $folder."
    # Get only files and only their names
    $folderFiles = Get-ChildItem -Path $Source_folder -File -Name
    foreach ($f in $files) {
        if ($folderFiles -contains $f) { 
            Write-Host "File $f was found." -foregroundcolor green
		
			##This is where i am stuck
			## need another loop within loop to check $f exist in $Destination_folder
			## if exist - just append the log tosay it exist
			
		
			
        } else { 
            Write-Host "File $f was not found!" -foregroundcolor red
			## if not copy from $Source_folder to $Destination_folder
			## catch and error log.
        }
    }

Many thanks once again.