Python - os.walk won't copy files from multiple folders - python

I have this script that hopefully moves all the files in multiple folders into a new folder. I used the os.walk and shtil.copy functions. However the script does not work.
Here is the script:
import os
import shutil
for root, dirs, filename in os.walk(r"C:\Users\edward\OneDrive\Suspensia Pictures"):
MoveFrom = r"C:\Users\edward\OneDrive\Suspensia Pictures"
MoveTo = r"C:\Users\edward\OneDrive\Pics"
shutil.copy(os.path.join(MoveFrom, filename), os.path.join(MoveTo, filename))
Here is the error I get:
TypeError: join() argument must be str, bytes, or os.PathLike object, not 'list'

import os
import shutil
from pathlib import Path
for path, subdirs, files in os.walk(r"C:\Users\edward\OneDrive\Suspensia Pictures"):
MoveFrom = r"C:\Users\edward\OneDrive\Suspensia Pictures"
MoveTo = r"C:\Users\edward\OneDrive\Pics"
for name in files:
shutil.copy(os.path.join(path, name), Path(MoveTo))

As the os.walk documentation said,
filenames is a list of the names of the non-directory files in dirpath.
which means that the filename in your code is type of list and that is not acceptable type for join().
Here's a possible way to solve it,
import os
import shutil
files: list
for root, dirs, files in os.walk(r"."):
source_path = r"."
target_path = r"../test"
for file in files:
if os.path.isfile(os.path.join(source_path)):
shutil.copy(os.path.join(source_path, file), os.path.join(target_path, file))
One thing that you should consider is that the files from the result of os.walk would be the files in each folder under the root, which is recursive. So, this script only is able to handle the files in the depth 1.
For moving all the files in each of the folder under your specific directory, this script may work.
import os
import shutil
files: list
for root, dirs, files in os.walk(r"."):
target_path = r"../test"
for file in files:
source_path = os.path.join(root, file)
shutil.copy(source_path, os.path.join(target_path, file))

Related

Python: Is there a better (cleaner/pythonic/faster) way to iterate over files and contained files in list of files and directories? [duplicate]

I'm trying to loop through a folder and all subfolders to find all files of certain file types - for example, only .mp4, .avi, .wmv.
Here is what I have now, it loops through all file types:
import os
rootdir = 'input'
for subdir, dirs, files in os.walk(rootdir):
for file in files:
print (os.path.join(subdir, file))
For multiple extensions, the simplest is just to use str.endswith passing a tuple of substrings to check:
for file in files:
if file.endswith((".avi",".mp4","wmv")):
print (os.path.join(subdir, file))
You could use iglob like below and chain the searches returned or use re.search but using endswith is probably the best approach.
from itertools import chain
from glob import iglob
for subdir, dirs, files in os.walk(rootdir):
for file in chain.from_iterable(iglob(os.path.join(rootdir,p)) for p in ("*.avi", "*.mp4", "*wmv")) :
print(os.path.join(subdir, file))
Using python3.5 glob now supports recursive searches with the ** syntax:
from itertools import chain
from glob import iglob
from glob import iglob
for file in chain.from_iterable(iglob(os.path.join(rootdir,p))
for p in (rootdir+"**/*.avi", "**/*.mp4", "**/*wmv")):
print(file)
You can use os.path.splitext which takes a path and splits the file extension from the end of it:
import os
rootdir = 'input'
extensions = ('.mp4', '.avi', '.wmv')
for subdir, dirs, files in os.walk(rootdir):
for file in files:
ext = os.path.splitext(file)[-1].lower()
if ext in extensions:
print (os.path.join(subdir, file))
I actually did something similar to this a couple of days ago and here is how I did it:
EXTENSIONS = ('.cpp','.hpp')
for root, dirs, files in os.walk(top):
for file in files:
if file.endswith(EXTENSIONS):
#file which ends with extension type so do your thing!
Hope this is what you are after. You can see the whole script here on my github.
This one line solution might also be useful to get all .py file in present directory
for file in list(filter(lambda x: x.endswith('.py'), os.listdir('./'))):
print(file)
Since Python 3.4 you can use pathlib:
from pathlib import Path
from itertools import chain
rootdir = 'input'
p = Path(rootdir)
for file in (chain(p.glob('**/*.mp4'), p.glob('**/*.avi'))):
print(file)

Iterate through directories, subdirectories, to get files with specialized ext. , copy in new directory

I have a question and I went all the other topics through with similar problems but I didn't get my solved.
I have a folder where two subfolders are. Inside of them are a lot of files, but I need just files with extension .trl. I need to copy them and save them in a new folder that is already created.
My code don't give me an error but I don't see any result. What I'm doing wrong?
import os
import shutil
import fnmatch
directory = "/home/.../test_daten"
ext = ('.trl')
dest_dir = "/home/.../test_korpus"
for root, dirs, files in os.walk(directory):
for extension in ext:
for filename in fnmatch.filter(files, extension+'.trl'):
source = (os.path.join(root, filename))
shutil.copy2(source, dest_dir)
Use os.walk() and find all files. Then use endswith() to find the files ending with .trl.
Sample code:
import os, shutil;
directory = "/home/.../test_daten";
dest_dir = "/home/.../test_korpus";
filelist = [];
for root, dirs, files in os.walk(directory):
for file in files:
filelist.append(os.path.join(root,file));
for trlFile in filelist:
if trlFile.endswith(".trl"):
shutil.copy(trlFile, dest_dir);
Maybe your problem is fnmatch.filter(files, extension+'.trl'). You have extension from for extension in ext: which will loop though the variable ext and give you a letter from it each time. Your extension+'.trl will be ..trl, t.trl, l.trl
import os
import shutil
directory = "/home/.../test_daten"
dest_dir = "/home/.../test_korpus"
for root, _, files in os.walk(directory): #Get the root, files
for x in files:
if x.endswith('.trl'): #Check the extension
shutil.copy2(f'{root}/{x}', dest_dir)
import os
import shutil
import fnmatch
source = "/home/.../test_daten"
ext = '*.trl'
target = "/home/.../test_korpus"
for root, _, files in os.walk(source):
for filename in fnmatch.filter(files, ext):
shutil.copy2(os.path.join(root, filename), target)

Python script to extract all subdirectories according to filename

My directory contains several folders, each with several subdirectories of their own. I need to move all of the files that contain 'Volume.csv' into a directory called Volume.
Folder1
|---1Area.csv
|---1Circumf.csv
|---1Volume.csv
Folder2
|---2Area.csv
|---2Circumf.csv
|---2Volume.csv
Volume
I'm trying combinations of os.walk and regex to retrieve the files by filename but not having much luck.
Any ideas?
Thank you!
Sunworshipper, thank you for the answer!
I ran the following code and it moved the entire directory rather than just file name containing 'Volume'. Is it clear why that happened?
import os
import shutil
source_dir = "~/Stats/"
dest_dir = "~/Stats/Volume/"
file_paths = set()
for dir_, _, files in os.walk(source_dir):
for fileName in files:
if "Volume" in fileName:
relDir = os.path.relpath(dir_, source_dir)
file_paths.add(relDir)
for matched in file_paths:
shutil.move(matched, dest_dir)
You can use glob for this. It returns a list of path names matching the expression you give it.
import glob
import shutil
dest = 'testfiles/'
files = glob.glob('*/*test.csv')
for file in files:
shutil.move(file, dest)
I used relative paths but you can also use absolute paths.
shutil moves the documents to the new location. See the glob.glob documentation for more info.
import os
import shutil
Setup your source and destination directories
source_dir = "/Users/nenad/Documents/Python Files/Random Tests"
dest_dir = "/Users/nenad/Documents/Python Files/Random Tests/volume"
This set will now hold paths of all files matching your substring.
file_paths = set()
Now I only consider the directories that contain a file which has a substring "hello" in the filename.
for dir_, _, files in os.walk(source_dir):
for fileName in files:
if "hello" in fileName:
relDir = os.path.relpath(dir_, source_dir)
relFile = os.path.join(relDir, fileName)
file_paths.add(relFile)
And now you just move them to your destination with shutil.
for matched in file_paths:
shutil.move(matched, dest_dir)
Sorry for the misread :)
Best regards

Move files from multiple directories to single directory

I am trying to use the os.walk() module to go through a number of directories and move the contents of each directory into a single "folder" (dir).
In this particular example I have hundreds of .txt files that need to be moved. I tried using shutil.move() and os.rename(), but it did not work.
import os
import shutil
current_wkd = os.getcwd()
print(current_wkd)
# make sure that these directories exist
dir_src = current_wkd
dir_dst = '.../Merged/out'
for root, dir, files in os.walk(top=current_wkd):
for file in files:
if file.endswith(".txt"): #match files that match this extension
print(file)
#need to move files (1.txt, 2.txt, etc) to 'dir_dst'
#tried: shutil.move(file, dir_dst) = error
If there is a way to move all the contents of the directories, I would be interested in how to do that as well.
Your help is much appreciated! Thanks.
Here is the file directory and contents
current_wk == ".../Merged
In current_wkthere is:
Dir1
Dir2
Dir3..
combine.py # python script file to be executed
In each directory there are hundreds of .txtfiles.
Simple path math is required to find source files and destination files precisely.
import os
import shutil
src_dir = os.getcwd()
dst_dir = src_dir + " COMBINED"
for root, _, files in os.walk(current_cwd):
for f in files:
if f.endswith(".txt"):
full_src_path = os.path.join(src_dir, root, f)
full_dst_path = os.path.join(dst_dir, f)
os.rename(full_src_path, full_dst_path)
You have to prepare the complete path of source file, and make sure dir_dst exists.
for root, dir, files in os.walk(top=current_wkd):
for file in files:
if file.endswith(".txt"): #match files that match this extension
shutil.move(os.path.join(root, file), dir_dst)

Python - Need to loop through directories looking for TXT files

I am a total Python Newb
I need to loop through a directory looking for .txt files, and then read and process them individually. I would like to set this up so that whatever directory the script is in is treated as the root of this action. For example if the script is in /bsepath/workDir, then it would loop over all of the files in workDir and its children.
What I have so far is:
#!/usr/bin/env python
import os
scrptPth = os.path.realpath(__file__)
for file in os.listdir(scrptPth)
with open(file) as f:
head,sub,auth = [f.readline().strip() for i in range(3)]
data=f.read()
#data.encode('utf-8')
pth = os.getcwd()
print head,sub,auth,data,pth
This code is giving me an invalid syntax error and I suspect that is because os.listdir does not like file paths in standard string format. Also I dont think that I am doing the looped action right. How do I reference a specific file in the looped action? Is it packaged as a variable?
Any help is appriciated
import os, fnmatch
def findFiles (path, filter):
for root, dirs, files in os.walk(path):
for file in fnmatch.filter(files, filter):
yield os.path.join(root, file)
Use it like this, and it will find all text files somewhere within the given path (recursively):
for textFile in findFiles(r'C:\Users\poke\Documents', '*.txt'):
print(textFile)
os.listdir expects a directory as input. So, to get the directory in which the script resides use:
scrptPth = os.path.dirname(os.path.realpath(__file__))
Also, os.listdir returns just the filenames, not the full path.
So open(file) will not work unless the current working directory happens to be the directory where the script resides. To fix this, use os.path.join:
import os
scrptPth = os.path.dirname(os.path.realpath(__file__))
for file in os.listdir(scrptPth):
with open(os.path.join(scrptPth, file)) as f:
Finally, if you want to recurse through subdirectories, use os.walk:
import os
scrptPth = os.path.dirname(os.path.realpath(__file__))
for root, dirs, files in os.walk(scrptPth):
for filename in files:
filename = os.path.join(root, filename)
with open(filename, 'r') as f:
head,sub,auth = [f.readline().strip() for i in range(3)]
data=f.read()
#data.encode('utf-8')

Categories

Resources