Search code examples
pythonfileconfigmove

Is there a way with python to move files on windows by reading origin and destination directories from a conf file?


I'm trying to automate moving files from one windows directory to another, having the origin and destination directories in a config file.

I've gotten it to work if there is only 1 line in the config file containing the paths. The shutil command also works if I hardcode the paths in the script, but that's not the idea. I need to loop through a list of directories and run the code per origin and destination

This is the entry in the .conf file:

c:\\temp\O D |c:\\temp\D D 

I split the line on the |, and and then I've tried the os.path.join and os.path.normpath but shutil keeps throwing the double backslashes if I add a row to the conf file.

If I add another row, then it throws this error:

FileNotFoundError: [Errno 2] No such file or directory: 'c:\temp\D D \test1.txt'

this is my code so far....

import shutil
import os
import os.path
import datetime

from pathlib import Path

filepath = r'c:\temp\acc.conf.txt'
with open(filepath) as fp:
   for cnt, line in enumerate(fp):
       print("Line {}: {}".format(cnt, line))

       a,b = line.split('| ')

       source= Path(a)
       source1=os.path.join(source)
       source_path = os.path.normpath(source1)
       #print(source_path)
       print(b)
       dst= Path(b)
       dst1=os.path.join(dst)
       dest_path = os.path.normpath(dst1)
       #print(dest_path)

       os.chdir(source_path)
       #print(os.getcwd())

       files = os.listdir(os.getcwd())
       now = datetime.datetime.now()
       run_time= now.strftime("%Y-%m-%d %H:%M:%S")
       for f in files:
           print(run_time + " - " + f + "- " + os.getcwd() + "- " + dest_path)
           #shutil.move(f, dest_path)
           print(f)
           print(dest_path)
           shutil.move(f, dest_path)

Solution

  • With some changes, I was able to fix your code and get it working on my computer.

    • Use strip() to remove the Windows style newline at the end of line and extra white space. This assumes that while your directory names might contain spaces, they won't end or start with a space.
    • Instead of doing chdir to source_path, I open it in place. This allows me to use relative paths instead of exclusively absolute ones, and there's really no need to change the dir anyway. As a result, the files in source_path are referred to via os.path.join(source_path, f).
    • Put a try/except around listdir to handle the case where the directory does not exist.
    • Test that dest_dir exists and is a directory, to avoid various problems.
    • I tested this script and it works on my Windows 10 machine with Python 3.9.5 called from PowerShell. It works with one or multiple lines, and the paths can use \\ or just \.
    import shutil
    import os
    import os.path
    import datetime
    
    from pathlib import Path
    
    filepath = r'c:\temp\acc.conf.txt'
    with open(filepath, "r") as fp:
       for cnt, line in enumerate(fp):
           print("Line {}: {}".format(cnt, line))
    
           a,b = line.split('|')
    
           source= Path(a.strip())
           source1=os.path.join(source)
           source_path = os.path.normpath(source1)
           print(b)
           dst= Path(b)
           dst1=os.path.join(dst)
           dest_path = os.path.normpath(dst1)
    
           if not os.path.isdir(dest_path):
               print(dest_path + " is not a directory, skipping.")
               continue
    
           try:
               files = os.listdir(source_path)
           except FileNotFoundError as e:
               print(e)
               continue
    
           now = datetime.datetime.now()
           run_time= now.strftime("%Y-%m-%d %H:%M:%S")
           for f in files:
               print(run_time + " - " + f + "- " + os.getcwd() + "- " + dest_path)
               print(f)
               print(dest_path)
               shutil.move(os.path.join(source_path, f), dest_path)