I would like to:
Write a script that takes a single directory path as command line argument, and then walks all subdirectories of that path looking for files with the extension '.py', copying each one to a temporary directory in your file system (eg /tmp/pyfiles). Your script should check for the existence of the temporary directory, and remove it if it already exists; it should then create a new directory, before beginning to copy files.
I have this:
#!/usr/bin/env python
import os, sys
import shutil
#import module
rootdir = sys.argv[1]
#take input directory
if os.path.exists('tmp/pyfiles'):
shutil.rmtree('tmp/pyfiles')
if not os.path.exists('tmp/pyfiles'):
os.makedirs('tmp/pyfiles')
#check whether directory exists, if it exists remove and remake, if not make
for root, dirs, files in os.walk(rootdir):
for f in files:
if os.path.splitext(f)[1] in ['.py']:
shutil.copy2(f, tmp/pyfiles)
#find files ending with .py, copy them and place in tmp/pyfiles directory
I get this error:
Traceback (most recent call last):
File "seek.py", line 20, in <module>
shutil.copy2(f, tmp/pyfiles)
NameError: name 'tmp' is not defined
Could anyone help me out?:) Thx
Your code says shutil.copy2(f, tmp/pyfiles), I believe it meant to be
shutil.copy2(f, 'tmp/pyfiles').
When you use the
os.walk()
method you loose track of the file full path. What I would do is to analyze each directory using the
os.listdir()
method and then copying each file taking into account its absolute path. Something like this:
for root, dirs, files in os.walk(rootdir):
for dir in dirs:
for f in os.listdir(dir):
if os.path.splitext(f)[1] in ['.py']:
shutil.copy2(os.path.join(root, dir, f), "tmp/pyfiles")
I hope this helps, maybe there is a cleaner solution.
You have to check if the root directory exists and walk in to remove everything if not create a new one.
To copy from dir to yours you have to check for files in dir that filename ends with .py, then replace the dir path with root path and create a new file in root dir with the content of matching file.
If we found a directory in dir we should create a new one in the root directory.
After that just call the function recursively to copy all content of dir to the root directory
import os, sys
rootdir = sys.argv[1]
PATH = "/tmp/pyfiles/"
def check(path, _file):
global rootdir, PATH
for item in os.listdir(path):
newpath = os.path.join(path, item)
if os.path.isdir(newpath):
os.mkdir(os.path.join(PATH, newpath.replace(rootdir, '')))
check(newpath, _file)
else:
if item.endswith(_file):
source = open(newpath, 'r')
print os.path.join(path, newpath.replace(rootdir, ''))
output = open(os.path.join(PATH, newpath.replace(rootdir, '')), 'w')
output.write(source.read())
output.close()
source.close()
if __name__ == '__main__':
if os.path.isdir(PATH):
for root, dirs, files in os.walk(PATH, topdown=False):
for name in files:
os.remove(os.path.join(root, name))
for name in dirs:
os.rmdir(os.path.join(root, name))
os.rmdir(PATH)
os.mkdir(PATH)
check(rootdir, '.py')
Related
Suppose that I have a working directory called directory 1. This directory has an app.py file and a directory file called directory2. Inside directory2 I have a text file called example.txt.
Is there a way of finding the path of example.txt using a command in app.py, knowing only the name of the text file and that it exists inside some directory of my working directory?
OS.walk() is what you are after.
Demo
import os
def find_file():
for root, dirs, files in os.walk(os.getcwd()):
if 'example.txt' in files:
path = os.path.join(root, 'example.txt')
print(f'file exists at {path}')
return
print('file does not exist')
find_file()
How can I extract all the .zip files in a certain directory to its parent directory?
I tried:
import zipfile
parent_directory = '../input'
directory = '../input/zip'
for f in os.listdir(directory):
with zipfile.ZipFile(os.path.join(directory,f), "r") as z:
z.extractall(parent_directory)
However the unzipped files are not saved in '..input/zip', they are saved in nested folders
This might be a bit exaggerated.
After files are unzipped, I run this to:
move the original .zip file up one directory level. (to avoid /src_filename' already exists error)
move all files from all subdirectories into the zip parent directory.
move the original .zip file back into the parent directory.
import os
import shutil
src = r'C:\Users\Owner\Desktop\PythonZip\PyUnzip01\child_dir\unzip_test2'
dest = r'C:\Users\Owner\Desktop\PythonZip\PyUnzip01\child_dir'
pdir = '../PyUnzip01'
os.replace(r"C:\Users\Owner\Desktop\PythonZip\PyUnzip01\child_dir\unzip_test2.zip", r"C:\Users\Owner\Desktop\PythonZip\PyUnzip01\unzip_test2.zip")
for root, subdirs, files in os.walk(src):
for file in files:
path = os.path.join(root, file)
shutil.move(path, dest)
os.replace(r"C:\Users\Owner\Desktop\PythonZip\PyUnzip01\unzip_test2.zip", r"C:\Users\Owner\Desktop\PythonZip\PyUnzip01\child_dir\unzip_test2.zip")
I am trying to collect all files with all sub-directories and move to another directory
Code used
#collects all mp3 files from folders to a new folder
import os
from pathlib import Path
import shutil
#run once
path = os.getcwd()
os.mkdir("empetrishki")
empetrishki = path + "/empetrishki" #destination dir
print(path)
print(empetrishki)
#recursive collection
for root, dirs, files in os.walk(path, topdown=True, onerror=None, followlinks=True):
for name in files:
filePath = Path(name)
if filePath.suffix.lower() == ".mp3":
print(filePath)
os.path.join
filePath.rename(empetrishki.joinpath(filePath))
I have trouble with the last line of moving files: filePath.rename() nor shutil.move nor joinpath() have worked for me. Maybe that's because I am trying to change the element in the tuple - the output from os.walk
Similar code works with os.scandir but this would collect files only in the current directory
How can I fix that, thanks!
If you use pathlib.Path(name) that doesn't mean that something exists called name. Hence, you do need to be careful that you have a full path, or relative path, and you need to make sure to resolve those. In particular I am noting that you don't change your working directory and have a line like this:
filePath = Path(name)
This means that while you may be walking down the directory, your working directory may not be changing. You should make your path from the root and the name, it is also a good idea to resolve so that the full path is known.
filePath = Path(root).joinpath(name).resolve()
You can also place the Path(root) outside the inner loop as well. Now you have an absolute path from '/home/' to the filename. Hence, you should be able to rename with .rename(), like:
filePath.rename(x.parent.joinpath(newname))
#Or to another directory
filePath.rename(other_dir.joinpath(newname))
All together:
from pathlib import os, Path
empetrishki = Path.cwd().joinpath("empetrishki").resolve()
for root, dirs, files in os.walk(path, topdown=True, onerror=None, followlinks=True):
root = Path(root).resolve()
for name in files:
file = root.joinpath(name)
if file.suffix.lower() == ".mp3":
file.rename(empetrishki.joinpath(file.name))
for root, dirs, files in os.walk(path, topdown=True, onerror=None, followlinks=True):
if root == empetrishki:
continue # skip the destination dir
for name in files:
basename, extension = os.path.splitext(name)
if extension.lower() == ".mp3":
oldpath = os.path.join(root, name)
newpath = os.path.join(empetrishki, name)
print(oldpath)
shutil.move(oldpath, newpath)
This is what I suggest. Your code is running on the current directory, and the file is at the path os.path.join(root, name) and you need to provide such path to your move function.
Besides, I would also suggest to use os.path.splitext for extracting the file extension. More pythonic. And also you might want to skip scanning your target directory.
I am trying to expose the selective path of a file, found using os.walk. The walk function is working correctly and is exposing all the files I want however right now I am able to expose either only the file name or full path of the file.
path = 'C:/Users/testing_recurssion'
for root, d_names, f_names in os.walk(path):
for name in f_names:
print(os.path.join(root, name))
This returns
C:/Users/testing_recurssion\folder1\file3.txt
C:/Users/testing_recurssion\folder1\folder3\file4.txt
However, I want it to return
folder1\file3.txt
folder1\folder3\file4.txt**
Use os.relpath
directory = "C:/Users/testing_recurssion"
for root, d_names, f_names in os.walk(directory):
for name in f_names:
path = os.path.join(root, name)
print(os.path.relpath(path, directory))
Also - consider using pathlib.Path which is more recent and object oriented:
from pathlib import Path
directory = Path("C:/Users/testing_recurssion")
for path in directory.rglob("*"):
print(path.relative_to(directory))
I am having a difficult time creating a python script that will rename file extensions in a folder and continue to do so in sub directories. Here is the script I have thus far; it can only rename files in the top directory:
#!/usr/bin/python
# Usage: python rename_file_extensions.py
import os
import sys
for filename in os.listdir ("C:\\Users\\username\\Desktop\\test\\"): # parse through file list in the folder "test"
if filename.find(".jpg") > 0: # if an .jpg is found
newfilename = filename.replace(".jpg","jpeg") # convert .jpg to jpeg
os.rename(filename, newfilename) # rename the file
import os
import sys
directory = os.path.dirname(os.path.realpath(sys.argv[0])) #get the directory of your script
for subdir, dirs, files in os.walk(directory):
for filename in files:
if filename.find('.jpg') > 0:
subdirectoryPath = os.path.relpath(subdir, directory) #get the path to your subdirectory
filePath = os.path.join(subdirectoryPath, filename) #get the path to your file
newFilePath = filePath.replace(".jpg",".jpeg") #create the new name
os.rename(filePath, newFilePath) #rename your file
I modified Jaron's answer with the path to the file and the complete example of renaming the file
I modified the answer of Hector Rodriguez Jr. a little bit because it would replace ANY occurance of ".jpg" in the path, e.g. /path/to/my.jpg.files/001.jpg would become /path/to/my.jpeg.files/001.jpeg, which is not what you wanted, right?
Although it is generally not a good idea to use dots "." in a folder name, it can happen...
import os
import sys
directory = os.path.dirname(os.path.realpath(sys.argv[0])) # directory of your script
for subdir, dirs, files in os.walk(directory):
for filename in files:
if filename.find('.jpg') > 0:
newFilename = filename.replace(".jpg", ".jpeg") # replace only in filename
subdirectoryPath = os.path.relpath(subdir, directory) # path to subdirectory
filePath = os.path.join(subdirectoryPath, filename) # path to file
newFilePath = os.path.join(subdirectoryPath, newFilename) # new path
os.rename(filePath, newFilePath) # rename
You can process the directory like this:
import os
def process_directory(root):
for item in os.listdir(root):
if os.path.isdir(item):
print("is directory", item)
process_directory(item)
else:
print(item)
#Do stuff
process_directory(os.getcwd())
Although, this isn't really necessary. Simply use os.walk which will iterate through all toplevel and further directories / files
Do it like this:
for subdir, dirs, files in os.walk(root):
for f in files:
if f.find('.jpg') > 0:
#The rest of your stuff
That should do exactly what you want.