使用 Python 从 Samba 复制目录/子目录中的所有文件



我正在尝试使用 Python 脚本从 Samba (SMB( 连接复制整个目录或目录中的所有文件及其子目录。我知道如何使用以下方法获取单个文件:

conn = SMBConnection('server',
'password',
'IP',
'share',
use_ntlm_v2 = True)
assert conn.connect('IP', 139)
x = 'test.txt'
with open(x, 'wb') as fp:
conn.retrieveFile('shared', '/EC/test/Pytest/Confocal/test.txt', fp)

但我想实现这样的东西:

root = "/home/to/directory/"
path = os.path.join(root, "source")
destination = "/home/to/target/directory/"
for path, subdirs, files in os.walk(root):
for name in files:
print (os.path.join(path, name))
if name.endswith(".nimp"):
shutil.move(os.path.join(path, name), destination)

获取具有特定类型(即 .nimp(的子目录中的所有文件。此代码在使用本地目录时有效,但我无法将其实现到 SMB 连接。 根据文档,没有复制整个文件夹的命令。我还想在 SMB 连接中动态保存文件作为其当前名称。有什么建议吗?

或者,我正在考虑复制整个文件夹,然后使用第二段代码复制所有文件,然后删除复制的文件夹。那也有可能吗?

另外,这个网站上没有帖子可以解决我的具体问题。

这里有一个可能对你有帮助的例子。

我省略了一些臃肿,这是我特定上下文中的一个例子,您应该专注于copyDir功能。这就是使用 samba 递归遍历目录并将其复制到本地机器的函数(也就是整个目录树将被复制相同,现有文件将被覆盖(。

#!/usr/bin/env python3
import os
import sys
import json
import getpass
from smb.SMBConnection import SMBConnection
from subprocess import Popen, PIPE
gameName = None
shareType = None
packToApply = None
basePath = None
def readUsername():
return ''
def readPw():
return ''
def copyPack(conn):
os.chdir(os.path.join(HOME_DIR, config_data.get('pathToEngineFromHome', ''), f"engine/games/{gameName}"))
for e in conn.listPath(SHARE_NAME, basePath):
if e.isDirectory and e.filename not in ['.', '..']:
copyDir(conn, e.filename)
def copyDir(conn, dirName):
dir = conn.listPath(SHARE_NAME, os.path.join(basePath, dirName))
for e in dir:
if not e.isDirectory:
filepath = os.path.join(dirName, e.filename)
with open(filepath, 'wb') as f:
conn.retrieveFile(SHARE_NAME, os.path.join(basePath, filepath), f)
elif e.filename not in ['.', '..']:
copyDir(conn, os.path.join(dirName, e.filename))
if __name__ == "__main__":
if gameName and type:
basePath = f'{gameName}/INT/{shareType}/{packToApply}/EXPORTS'
username = readUsername()
pw = readPw()

# create samba connection
conn = SMBConnection(username, pw, 'AIAIAI', 'SERVER', use_ntlm_v2=True)
assert conn.connect(SHARES_SERVER)
copyPack(conn)
conn.close()

吃巧克力的解决方案对我来说不太有用,但是我想出了一个确实有效的变体:

import pathlib
def copyDir(conn, remote_path: str, local_path: str, share_name: str) -> None:
''' Copy remote SMB directory recursively from `remote_path` to `local_path`'''
contents = conn.listPath(share_name, remote_path)
for e in contents:
remote_file = os.path.join(remote_path, e.filename)
local_file  = os.path.join(local_path,  e.filename)

if not e.isDirectory:
# It's a file -> Download
pathlib.Path(local_path).mkdir(parents=True, exist_ok=True)
with open(local_file, 'wb') as fs:
conn.retrieveFile(share_name, remote_file, fs)

elif e.filename not in ['.', '..']:
# It's not a file -> Recurse
copyDir(conn, remote_file, local_file, share_name)

最新更新