I have a scenario where I need to ftp thousands of files from a remote server to an intermediate - the intermediate has the ftp server installed - then from there to the destination server, Due to security I cannot ftp direct from remote to destination.
I have a Powershell script for each of the 2 steps, each script creates a FileZilla Pro CLI script per subdirectory.
My 1st script works as expected, iterating over all folders and subfolders, doing a put where newer or a different size.
The 2nd script I cannot get to work, it does not seem to work out the remote(intermediate) and local paths properly, or create folders locally if not existing(where they exist on remote).
I have included only the relevant parts of each script, as an example for the 2nd script, local root would be ‘F:\MyDir\Images’ and on remote the root is ‘\Images’
1st push script - remote to intermediate:
Add-DirectoryCommands -localPath $dirPath -remotePath $remoteDirPath -filezillaCommands ([ref]$filezillaCommands)
# Iterate over each subfolder and file in the current directory, including nested subfolders
Get-ChildItem -Path $dirPath -Recurse | ForEach-Object {
if ($_.PSIsContainer) {
# Create the directory on the remote server
$relativePath = $_.FullName.Substring($localDirectory.Length) -replace "\\", "/"
$remoteSubDirPath = "$remoteDirPath/$relativePath"
Add-DirectoryCommands -localPath $_.FullName -remotePath $remoteSubDirPath -filezillaCommands ([ref]$filezillaCommands)
$dirsCreated++
} else {
# Increment the files checked counter
$filesChecked++
$globalFilesChecked++
# Prepare local and remote file paths
$localFile = $_.FullName -replace "\\", "/"
$relativePath = $_.DirectoryName.Substring($dirPath.Length) -replace "\\", "/"
$remoteFilePath = if ($relativePath) { "$remoteDirPath/$relativePath/" + $_.Name } else { "$remoteDirPath/" + $_.Name }
# Add file upload command
#log-message "$localFile to $remoteFilePath"
$filezillaCommands += "put --exists size_newer `"$localFile`" `"$remoteFilePath`""
$filesCopied++
$globalFilesCopied++
}
}
Hard to tell. Do you have any errors ? I am kind of suprised that Filezilla does not have a sync directories command. I guess script 1 is running on a server and script 2 on the intermediate server ?
On the second script, I do see that you prepare the Filezilla command, but I don’t see any place where you are executing it. I guess you hide it out.
Also to make sure, I would first deal with all directories with the command get-childitem -Directory and verify on the target with the command `Test-Path. And I would copy files after.
Zipping may also be an easier way to deal with directories.
If $rootFolder is a string rather than a DirectoryInfo object, it won’t have a FullName property. When Get-ChildItem runs it will run over the current folder, which won’t be the folder referenced by $rootFolder unless you happen to be running the script from that directory.
@ZaMotH@matt-bloomfield Thanks for the quick replies, they’ve given me something to think about.
Just for clarity, this is the full script. I think what I actually need to do is
Start from remote and iterate over all folders off root recursively,
If the folder or its children don’t exist on local then create the folder/child folders,
then create the fielzilla script as I’m doing, per folder off root.
# Log the start of checking the current root folder
Log-Message "Starting check for root folder: $($rootFolder.FullName)"
# Generate the initial part of the FileZilla CLI script for each root folder
$scriptContent = @"
open sftp://${ftpUser}:${ftpPass}@${ftpHost}:22
lcd $localDirectory
"@
# Iterate over each subfolder and file within the current root folder, including nested subfolders
Get-ChildItem -Path $rootFolder.FullName -Recurse | ForEach-Object {
if ($_.PSIsContainer) {
# Create the directory on the remote server
$relativePath = $_.FullName.Substring($rootFolder.FullName.Length) -replace "\\", "/"
$remoteDirPath = "./$relativePath"
$scriptContent += "mkdir $remoteDirPath" + "`n"
} else {
# Increment the files checked counter
$global:filesChecked++
# Prepare the download command
$localFile = $_.FullName -replace "\\", "/"
$relativePath = $_.DirectoryName.Substring($rootFolder.FullName.Length) -replace "\\", "/"
$remoteFilePath = if ($relativePath) { "./$relativePath/" + $_.Name } else { "./" + $_.Name }
log-message "$remoteFilePath to $localFile"
# $scriptContent += "get --exists size_newer `"$remoteFilePath`" `"$localFile`"" + "`n"
}
}
# Finish the script with the quit command
$scriptContent += "`nquit" + "`n"
# Create a temporary script file for FileZilla CLI for each root folder
$tempScriptPath = "C:\temp\filezilla_script_$($rootFolder.Name).txt"
$scriptContent | Out-File -FilePath $tempScriptPath -Encoding ASCII
# Run FileZilla CLI with the generated script
try {
Start-Process -FilePath $filezillaPath -ArgumentList "--script=$tempScriptPath" -Wait
} catch {
Log-Message "Error during FileZilla CLI execution for folder $($rootFolder.Name): $_"
}
# Clean up temporary script file
Remove-Item -Path $tempScriptPath
# Log the completion for this root folder
Log-Message "Completed download for root folder $($rootFolder.Name)"