I have some code for reading directory names and file names
import os
#define the folder you want to use
myfolder = path/to/directory
#read directories
for dirs in os.walk(myfolder):
for dir in dirs:
print("Directory name = %s" %dir
lets say inside -myfolder- I have a directory called -mysecondfolder-
is it possible to output the filename to a string
something like
for dirs in os.walk(myfolder):
for dir in dirs:
targetfolder="%dir"
You could try like this:
for root, dirs, files in os.walk(myfolder, topdown=False):
targetfolder = dirs
Related
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 want to change the file names and folder names in a given directory and all subfolders. My folder structure is as follows:
top directory
file1
file2
folder1
file1
file2
file3
file4
folder2
file1
file2
file3
file4
I get the following error when executing the code below. I already checked the forums, but couldn't find a solution. Could someone please help me solve this issue and let me know what I need to do to get the program working?
Or is there a better solution for renaming files and folders in a tree?
Error message
FileNotFoundError: [WinError 2] The system cannot find the file specified: 'Filename 1' -> 'filename_1'
Code
#Change file names and folder names in a given directory and all its
subfolders
import os
os.chdir("path\\to\\folder")
print(os.getcwd())
#Walk the directory and change the file names and folder names in all folders and subfolders.
for root, dirs, files in os.walk("path\\to\\folder"):
for dir_name in dirs:
os.rename(dir_name, dir_name.replace(" ", "_").lower())
for file_name in files:
os.rename(file_name, file_name.replace(" ", "_").lower())
#Print done once all files have been renamed.
print("done")
You need to use root otherwise the rename can't find the path:
for root, dirs, files in os.walk("path/to/folder"):
for name in dirs + files:
os.rename(os.path.join(root, name), os.path.join(root, name.replace(" ", "_").lower()))
could it be that you're walking on a folder while renaming it so that it can't be found?
looks like you first need to rename the files and only then the dirs (and even then - make sure it's bottom up)
Try to change the filename first, otherwise you'll change the dir_name and lose reference.
Following solution works most of the time, still issues like same name files may exist after normalizing the name.
import os
os.chdir("path/to/dir")
print(os.getcwd())
#Walk the directory and change the file names and folder names in all folders and subfolders.
for root, dirs, files in os.walk("path/to/dir", topdown=False):
for file_name in files:
new_name = file_name.replace(" ", "_").lower()
if (new_name != file_name):
os.rename(os.path.join(root, file_name), os.path.join(root, new_name))
for dir_name in dirs:
new_name = dir_name.replace(" ", "_").lower()
if (new_name != dir_name):
os.rename(os.path.join(root, dir_name), os.path.join(root, new_name))
Here I copied all files inside of each subfolder to another path.
First use os.listdir() to move through each folder, then use it to move through files which are inside of the folder path. Finally use os.rename() to rename file name. Here, I changed file name to folder name_file name which is "folder_file":
path = 'E:/Data1'
path1 = 'E:/Data2'
for folder in os.listdir(path):
for file in os.listdir(path + '/'+ folder):
src = path + '/' + folder + '/' + file
des = path1 + '/' + folder + '_' +file
os.rename(src, des)
I am trying to go through a bunch of folders and go into each one and rename specific files to different names. I got stuck on just the loop through folders part.
My file system looks as follows:
Root Directory
Folder
File1
File2
File3
Folder
File1
File2
File3
The code I have is:
os.chdir(rootDir)
for folder in os.listdir():
print(folder)
os.chdir(rootDir + 'folder')
for f in os.listdir():
print(f)
os.chdir(rootDir)
So in my mind it will go through the folders then enter the folder and list the files inside then go back to the root directory
Have a look at os.walk
import os
for dir, subdirs, files in os.walk("."):
for f in files:
f_new = f + 'bak'
os.rename(os.path.join(root, f), os.path.join(root, f_new))
You need os.walk. It returns a 3-tuple (dirpath, dirnames, filenames) that you can iterate.
def change_files(root_dir,target_files,rename_fn):
for fname in os.listdir(root_path):
path = os.path.join(root_path,fname)
if fname in target_files:
new_name = rename_fn(fname)
os.move(path,os.path.join(root_path,new_name)
def rename_file(old_name):
return old_name.replace("txt","log")
change_files("/home/target/dir",["File1.txt","File2.txt"],rename_file)
I'm having troubles finding and deleting empty folders with my Python script.
I have some directories with files more or less like this:
A/
--B/
----a.txt
----b.pdf
--C/
----d.pdf
I'm trying to delete all files which aren't PDFs and after that delete all empty folders. I can delete the files that I want to, but then I can't get the empty directories. What I'm doing wrong?
os.chdir(path+"/"+name+"/Test Data/Checklists")
pprint("Current path: "+ os.getcwd())
for root, dirs, files in os.walk(path+"/"+name+"/Test Data/Checklists"):
for name in files:
if not(name.endswith(".pdf")):
os.remove(os.path.join(root, name))
pprint("Deletting empty folders..")
pprint("Current path: "+ os.getcwd())
for root, dirs, files in os.walk(path+"/"+name+"/Test Data/Checklists", topdown=False):
if not dirs and not files:
os.rmdir(root)
use insted the function
os.removedirs(path)
this will remove directories until the parent directory is not empty.
Ideally, you should remove the directories immediately after deleting the files, rather than doing two passes with os.walk
import sys
import os
for dir, subdirs, files in os.walk(sys.argv[1], topdown=False):
for name in files:
if not(name.endswith(".pdf")):
os.remove(os.path.join(dir, name))
# check whether the directory is now empty after deletions, and if so, remove it
if len(os.listdir(dir)) == 0:
os.rmdir(dir)
For empty folders deletion you can use this snippet.
It can be combined with some files deletion, but as last run should be used as is.
import os
def drop_empty_folders(directory):
"""Verify that every empty folder removed in local storage."""
for dirpath, dirnames, filenames in os.walk(directory, topdown=False):
if not dirnames and not filenames:
os.rmdir(dirpath)
remove all empty folders
import os
folders = './A/' # directory
for folder in list(os.walk(folders)) :
if not os.listdir(folder[0]):
os.removedirs(folder[0])
how can i get the folder names existing in a directory using Python ?
I want to save all the subfolders into a list to work with the names after that but i dont know how to read the subfolder names ?
Thanks for you help
You can use os.walk()
# !/usr/bin/python
import os
directory_list = list()
for root, dirs, files in os.walk("/path/to/your/dir", topdown=False):
for name in dirs:
directory_list.append(os.path.join(root, name))
print directory_list
EDIT
If you only want the first level and not actually "walk" through the subdirectories, it is even less code:
import os
root, dirs, files = os.walk("/path/to/your/dir").next()
print dirs
This is not really what os.walk is made for. If you really only want one level of subdirectories, you can also use os.listdir() like Yannik Ammann suggested:
root='/path/to/my/dir'
dirlist = [ item for item in os.listdir(root) if os.path.isdir(os.path.join(root, item)) ]
print dirlist
Starting with Python 3.4, you can also use the new pathlib module:
from pathlib import Path
p = Path('some/folder')
subdirectories = [x for x in p.iterdir() if x.is_dir()]
print(subdirectories)
You can use os.listdir() here a link to the docs
Warning returns files and directories
example:
import os
path = 'pyth/to/dir/'
dir_list = os.listdir(path)
update: you need to check if the returned names are directories or files
import os
path = 'pyth/to/dir/'
# list of all content in a directory, filtered so only directories are returned
dir_list = [directory for directory in os.listdir(path) if os.path.isdir(path+directory)]
You should import os first.
import os
files=[]
files = [f for f in sorted(os.listdir(FileDirectoryPath))]
This would give you list with all files in the FileDirectoryPath sorted.
I use os.listdir
Get all folder names of a directory
folder_names = []
for entry_name in os.listdir(MYDIR):
entry_path = os.path.join(MYDIR, entry_name)
if os.path.isdir(entry_path):
folder_names.append(entry_name)
Get all folder paths of a directory
folder_paths = []
for entry_name in os.listdir(MYDIR):
entry_path = os.path.join(MYDIR, entry_name)
if os.path.isdir(entry_path):
folder_paths.append(entry_path)
Get all file names of a directory
file_names = []
for file_name in os.listdir(MYDIR):
file_path = os.path.join(MYDIR, file_name)
if os.path.isfile(file_path):
file_names.append(file_name)
Get all file paths of a directory
file_paths = []
for file_name in os.listdir(MYDIR):
file_path = os.path.join(MYDIR, file_name)
if os.path.isfile(file_path):
file_paths.append(file_path)
For python 3 I'm using this script
import os
root='./'
dirlist = [ item for item in os.listdir(root) if os.path.isdir(os.path.join(root, item)) ]
for dir in dirlist:
print(dir)
Use os.walk(path)
import os
path = 'C:\\'
for root, directories, files in os.walk(path):
for directory in directories:
print os.path.join(root, directory)
Python 3.x: If you want only the directories in a given directory, try:
import os
search_path = '.' # set your path here.
root, dirs, files = next(os.walk(search_path), ([],[],[]))
print(dirs)
The above example will print out a list of the directories in the current directory like this:
['dir1', 'dir2', 'dir3']
The output contains only the sub-directory names.
If the directory does not have sub-directories, it will print:
[]
os.walk() is a generator method, so use next() to only call it once. The 3-tuple of empty strings is for the error condition when the directory does not contain any sub-directories because the os.walk() generator returns 3-tuples for each layer in the directory tree. Without those, if the directory is empty, next() will raise a StopIteration exception.
For a more compact version:
dirs = next(os.walk(search_path), ([],[],[]))[1]