是否可以在 Python 中使用 SCP 从目录传输文件但忽略隐藏文件或符号链接?

Is it possible to transfer files from a directory using SCP in Python but ignore hidden files or sym links?

我目前正在 Python 中使用 Paramiko 和 SCPClient 将目录从一台服务器传输到另一台服务器作为备份方式。这很好用,但我不希望它复制隐藏文件 (.file_name) 或符号链接。这可能吗?

不幸的是,rsync 对我来说不是一个选项,因为它在我连接的任何一个远程服务器上都不可用。我的脚本如下(敏感信息替换为虚拟数据)。请注意,在连接到 target_1 或 target_2.

之前,我需要连接到跳转主机
import os
import shutil
import time
import paramiko
from scp import SCPClient

#set up ssh variables
j_host = '00.00.00.00'
target_host_1 = '00.00.00.001'
target_host_2 = '00.00.00.002'
port_no = 22
username = ''
passw = ''

#set up temporary folder on local machine to store files
path = "/local_path/"
os.mkdir(path)

#create SSH Client for jump server
jump_host=paramiko.SSHClient()
jump_host.set_missing_host_key_policy(paramiko.AutoAddPolicy())
jump_host.connect(j_host, username=username, password=passw)

#set up channel to connect to 1 via jump server
jump_host_transport_1 = jump_host.get_transport()
src_addr = (j_host, port_no)
dest_addr_1 = (target_host_1, port_no)
jump_host_channel_1 = jump_host_transport_1.open_channel("direct-tcpip", dest_addr_1, src_addr)

#set up channel to connect to 2 via jump server
jump_host_transport_2 = jump_host.get_transport()
dest_addr_2 = (target_host_2, port_no)
jump_host_channel_2 = jump_host_transport_2.open_channel("direct-tcpip", dest_addr_2, src_addr)

#function which sets up target server, either 1 or 2
def create_SSHClient(server, port, user, password, sock):
    target=paramiko.SSHClient()
    target.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    target.connect(server, port, user, password, sock=sock)
    return target

#invoke above function to set up connections for 1 & 2
ssh_1 = create_SSHClient(target_host_1, port_no, username, passw, jump_host_channel_1)
ssh_2 = create_SSHClient(target_host_2, port_no, username, passw, jump_host_channel_2)

#delete old files in backup folder
command = "rm -rf /filepath/{*,.*}"
stdin, stdout, stderr = ssh_2.exec_command(command)
lines = stdout.readlines()
#print(lines)

#pause to ensure old directory is cleared
time.sleep(5)

#SCPCLient takes a paramiko transport as an argument, sets up file transfer connection
scp_1 = SCPClient(ssh_1.get_transport())
scp_2 = SCPClient(ssh_2.get_transport())

#get files from 1, store on local machine, put on 2
scp_1.get('/filepath/.', '/target_folder_local/', recursive=True)
scp_2.put('/target_folder_local/.', '/filepath/', recursive=True)

#remove temporary folder
shutil.rmtree(path)

#close connections
ssh_1.close()
ssh_2.close()
jump_host.close()

SCPClient 中没有 API 可以跳过隐藏文件或符号链接。


对于上传,很简单,如果你复制SCPClient's code并根据需要修改它。请参阅 _send_recursive 函数中的 os.walk 循环。

如果您不想修改 SCPClient 的代码,您将不得不自己迭代文件,为每个文件调用 SCPClient.put。它的效率会有所降低,因为它会为每个文件启动新的 SCP 服务器。


对于下载,您可以修改 SCPClient 代码以使用非零代码响应服务器为您不想下载的文件提供的 C 命令。

检查_recv_file函数。在解析 name 的地方,检查您不想下载的文件的名称或属性,然后执行 chan.send('\x01') 并退出该函数。


虽然你为什么要使用SCP?使用 SFTP。它更适合您需要的自定义规则。

Paramiko 没有递归 SFTP 传输功能(但是 pysftp 有,参见 )。但是无论如何你都不能使用它,因为同样的原因你不能将它与 SCP 一起使用。满足您的特定需求。

但请检查我对 的回答。它显示了一个简单的递归 SFTP 下载代码。稍微修改一下,跳过不想下载的文件。

类似

if (not S_ISLNK(mode)) and (not entry.filename.startswith(".")):

(参见