Recently, I had to rename all space characters used in the directory and file names in a Samba tree.
Before that, I used os.walk
to traverse the directory tree of regular files in python, but I wanted to rename them in-place.
To connect to my Samba server and rename a single file, I used this snippet:
from smb import SMBConnection
conn = SMBConnection.SMBConnection(userID, password, client_machine_name, server_name, is_direct_tcp=True, domain='workgroup')
assert conn.connect('1.2.3.4')
shares = conn.listShares()
for share in shares:
if share.name == 'share':
conn.rename('share', 'path/old_name', 'path/new_name')
My problem is when I rename parent directories to new names, I can't access their children anymore. How can I rename old directories and files recursively using pysmb
?
Finally I find a sample code as follow in pysmb here as os.walk
:
def smb_walk(conn, shareddevice, top='/'):
dirs, nondirs = [], []
if not isinstance(conn, SMBConnection.SMBConnection):
raise TypeError("SMBConnection required")
names = conn.listPath(shareddevice, top)
for name in names:
if name.isDirectory:
if name.filename not in [u'.', u'..']:
dirs.append(name.filename)
else:
nondirs.append(name.filename)
yield top, dirs, nondirs
for name in dirs:
new_path = os.path.join(top, name)
for x in smb_walk(conn, shareddevice, new_path):
yield x
Then I rename directories and files recursively from the innermost directory (because the files path name before them name renaming sholdn't changed):
ans = smb_walk(conn, 'share', top=source_path)
smb_l = list(ans)
for s_i in smb_l[::-1]:
for s_j in s_i[2][::-1]:
if s_j:
#rename file name
conn.rename('share', f'{s_i[0]}/{s_j}', f'{s_i[0]}/{encode_n(s_j)}')
for s_j in s_i[1][::-1]:
if s_j:
#rename directory name
conn.rename('share', f'{s_i[0]}/{s_j}', f'{s_i[0]}/{encode_n(s_j)}')