Print file data during a for loop - python

I have to propose this question again, I'm a newbie in Python and I can't resolve this.
I'm trying to print the filename and the filesize during this for loop when the file is moved to the new folder. I know the os.path.getsize(path) and os.stat(path).st_size methods, but which path can I enter if my file change every loop?
This code hasn't errors, but I don't know how to print the data during the loop as the file change.
src = ("C:\\..\\files")
dest1 = ("C:\\..\\files\\images")
files = os.listdir(src) #files is a list of files in a folder
for file in files:
if file.endswith(".jpg") or file.endswith(".png") or file.endswith(".jpeg"):
if not os.path.exists(dest1):
os.mkdir(dest1)
shutil.move(src + "/" + file, dest1) #for every file that is moved I have to print filesize and filename.
#print(??)

IIUC, try:
src = ("C:/Users/username/")
with open("recap.csv", "w") as recap_file:
csv_writer = csv.writer(recap_file, delimiter="\t")
for file in os.listdir(src):
if file.endswith(".jpg") or file.endswith(".png") or file.endswith(".jpeg"):
dest = f"{src}/images"
elif file.endswith(".odt") or file.endswith(".txt"):
dest = f"{src}/docs"
elif file.endswith(".mp3"):
dest = f"{src}/audios"
else:
continue
size = os.path.getsize(f"{src}/{file}")
print(f"File name: {src}/{file}; Size: {size}")
csv_writer.writerow([f"{src}/{file}", size])
if not os.path.exists(dest):
os.mkdir(dest)
shutil.move(f"{src}/{file}", dest)

Moving the file should generally not change the file size [1], so you can check the file's size before performing the move.
On the other hand, since you know where you move the file, you could also determine files size after the move. Moving a file from src + "/" + file to dest1 means that the file should be at dest1 + "/" + file after the operation[2]. You can use this to not only print the new path of the file, but also determine the file's size at the new location.
[1] (NB: file size can change when moving from one file system to another, with different block sizes and size specified as a multiple of the block size. However, this should not be a problem for this case.)
[2] Moving the file could fail for a number of reasons (file was deleted intermittently, there is already a (write-protected) file with that name at the destination, no space left in destination, ...). You should add some error handling for such cases, e.g. with a try ... except block around the shutil.move operation.

Related

How to read file contents of files in a directory and create copies into a new directory?

I have to complete this function according to these instructions, I have tried looping thru with for loop and ever the os.path approach but still cant figure it out? how can I Improve upon this?
def copy_files():
Open each .txt file in the datafiles folder.
datafiles contain 10 .txt files with numbers separated by ','. Each file in datafiles is named file00, file01, file0(+=1)...
Read in the text and then write it back out to an identically named file in the mydatafiles sub-folder within the myfiles folder.
You have to achieve this by reading in the text from each file as a string and then writing it back out to the new file.
This function requires no error handling and has no return value.
When done, the mydatafiles folder will contain a copy of each file within the datafiles folder.
from shutil import copyfile
def copy_files():
src_files = os.listdir('datafiles')
for file_name in src_files:
full_file_name = os.path.join('datafiles', file_name)
if os.path.isfile(full_file_name):
copyfile(full_file_name, 'mydatafiles')
Alternative approach:
from shutil import copyfile
def copy_files():
completeName = os.path.join('myfiles', "mydatafiles")
new_file = " "
for file in 'datafiles':
new_file += file
incompleteName = os.path.join('datafiles', new_file)
with open(incompleteName,'r') as firstfile, open('completeName','a') as secondfile:
for line in firstfile:
# write content to second file
secondfile.write(line)
I'd appreciate any help
for shutil.copyfile(src, dst) destination must complete filename not directory, use copy() to use directory as destination
def copy_files():
src_files = os.listdir('datafiles')
for file_name in src_files:
full_file_name = os.path.join('datafiles', file_name)
if os.path.isfile(full_file_name):
targetFile = os.path.join('mydatafiles', file_name)
copyfile(full_file_name, targetFile)
# or
# copy(full_file_name, 'mydatafiles')

How to fix 'NotADirectoryError' in Python on Mac

I'm trying to walk through all the files on my computer and create a list of files larger than 100MB. However, when walking through the files, I keep getting a 'NotADirectoryError.' The way I understand my code, it should be looking base files in the second for loop, so I don't know why the 'NotADirectory' Error keeps getting raised.
I'm on a Mac using Python3.7.4. I've tried adding an exception for 'NotADirectoryError', but it just gave me a 'FileNotFound Error,' so I figured adding exception upon exception wasn't the best way to solve this.
I think I'm misunderstanding how either os.walk or os.path.getsize work, but after reviewing the documentation for both I'm still confused about what I'm doing wrong.
big_dict= {}
folder = os.path.abspath('/Users/')
#walking thru all the folders on my computer
for folders, subfolders, filenames in os.walk(folder):
#for each file that's bigger than 100 MB, add it to the 'big_dict'
for filename in filenames:
filename = os.path.join(folder, filename) +'/'
file_size = os.path.getsize(filename) -- this line always gives the error
#convert size to MB, add to big_dict as value with filename key
if file_size > 1000000:
big_dict[filename] = str(file_size/10000) + ' MB'
Traceback (most recent call last):
File "/Users/jonbauer/size_check.py", line 17, in <module>
file_size = os.path.getsize(filename)
File "/Applications/Thonny.app/Contents/Frameworks/Python.framework/Versions/3.7/Resources/Python.app/Contents/MacOS/../../../../../../../Python.framework/Versions/3.7/lib/python3.7/genericpath.py", line 50, in getsize
return os.stat(filename).st_size
NotADirectoryError: [Errno 20] Not a directory: '/Users/.localized/'
This is the error message I get when running the code. As I said before, I'm trying to walk through all my files and add larger files to a list, but I keep encountering this error.
big_dict= {}
folder = os.path.abspath('/Users')
for root, _, filenames in os.walk(folder):
for filename in filenames:
path = os.path.join(root, filename)
if os.path.islink(path):
continue
file_size_mb = os.path.getsize(path) >> 20
if file_size_mb > 100:
file_size_mb_str = '{} MB'.format(file_size_mb)
print(path, file_size_mb_str)
big_dict[path] = file_size_mb_str
There are several problems in your code:
filename = os.path.join(folder, filename) +'/' is incorrect, because folder is the base folder ('/Users/' in your case), not the actual folder you're walking.
You need to skip links, because getsize() won't work on them
file_size > 1000000: os.path.getsize() returns bytes

How to save files with same name in folder in python?

I have two folders with images. Let the two folder names A and B. A contains 100 files and B has only 80 files. Both the files have the same name. I want to save only the 80 files from A which has the same correspondence to B in folder C.
Here is a part of my code. However, it is throwing error :
Required argument 'img' (pos 2) not found.
path1= '/home/vplab/Kitty/Saliency Dataset/PiCANet-Implementation/TrainSet/images'
path_mask= '/home/vplab/Kitty/Saliency Dataset/PiCANet-Implementation/TrainSet/masks'
save_path = '/home/vplab/Kitty/Saliency Dataset/PiCANet-Implementation/TrainSet/exp'
for file in os.listdir(path1):
for file1 in os.listdir(path_mask):
img_name = file[:-4]
mask_name =file1[:-4]
if img_name == mask_name:
cv2.imwrite(os.path.join(save_path,img_name))
Your issue here is that you are not passing a file object to cv2.imwrite(os.path.join(save_path,img_name)) when trying to perform the copy; that's what the error is telling you.
However, your current approach includes a nested for loop which will give poor performance. If you only want to know the files that the directories have in common, you can create a set of the file names in each directory and find the intersection. Then you just need to iterate through the common files and copy them over (as said in the comments, there's no need for cv2 here - they may be images but they're just regular files that can be copied).
import os
from shutil import copyfile
dir_1 = 'A'
dir_2 = 'B'
output_dir = 'C'
files_1 = os.listdir(dir_1)
files_2 = os.listdir(dir_2)
# Find the common files between both
common_files = set(files_1).intersection(files_2)
# Copy the common files over.
for file in common_files:
copyfile(os.path.join(dir_1, file),
os.path.join(output_dir, file))
If the reason that you are stripping the last characters from the files in os.listdir is because the files have the same name but different extensions, you only need to make two small modifications (where here I'm assuming the extension is .png that needs to be added back later):
files_1 = [item[:-4] for item in os.listdir(dir_1)]
files_2 = [item[:-4] for item in os.listdir(dir_2)]
And:
for file in common_files:
file = file + '.png' # Add the extension back on to the file name
copyfile(os.path.join(dir_1, file),
os.path.join(output_dir, file))
The any() method returns True if any element of an iterable is True. If not, any() returns False. shutil.copy - Copies the file src to the file or directory dst.
import os
import shutil
def read_file(folderName,folderPath):
''' Return list of files name '''
path = folderPath+folderName
return [file for file in os.listdir(path)]
def save_file(soureFolderName,destFolderName,folderPath,fileName):
''' Save file on destination folder'''
try:
source_path = folderPath+soureFolderName+"/"+fileName
dest_path = folderPath+destFolderName+"/"+fileName
shutil.copy(source_path, dest_path)
except Exception as e:
print(e)
base_path = '/home/vplab/Kitty/Saliency Dataset/PiCANet-Implementation/TrainSet/'
folder_images_files = read_file('images',base_path)
folder_masks_file = read_file('masks',base_path)
for file_1 in folder_images_files:
#Check folder A file is exists in folder B
if any(file_1 == file_2 for file_2 in folder_masks_file):
save_file("images","exp",base_path,file_1)

Cannot find the file specified when batch renaming files in a single directory

I've created a simple script to rename my media files that have lots of weird periods and stuff in them that I have obtained and want to organize further. My script kinda works, and I will be editing it to edit the filenames further but my os.rename line throws this error:
[Windows Error: Error 2: The system cannot find the file specified.]
import os
for filename in os.listdir(directory):
fcount = filename.count('.') - 1 #to keep the period for the file extension
newname = filename.replace('.', ' ', fcount)
os.rename(filename, newname)
Does anyone know why this might be? I have a feeling that it doesn't like me trying to rename the file without including the file path?
try
os.rename(filename, directory + '/' + newname);
Triton Man has already answered your question. If his answer doesn't work I would try using absolute paths instead of relative paths.
I've done something similar before, but in order to keep any name clashes from happening I temporarily moved all the files to a subfolder. The entire process happened so fast that in Windows Explorer I never saw the subfolder get created.
Anyhow if you're interested in looking at my script It's shown below. You run the script on the command line and you should pass in as a command-line argument the directory of the jpg files you want renamed.
Here's a script I used to rename .jpg files to multiples of 10. It might be useful to look at.
'''renames pictures to multiples of ten'''
import sys, os
debug=False
try:
path = sys.argv[1]
except IndexError:
path = os.getcwd()
def toint(string):
'''changes a string to a numerical representation
string must only characters with an ordianal value between 0 and 899'''
string = str(string)
ret=''
for i in string:
ret += str(ord(i)+100) #we add 101 to make all the numbers 3 digits making it easy to seperate the numbers back out when we need to undo this operation
assert len(ret) == 3 * len(string), 'recieved an invalid character. Characters must have a ordinal value between 0-899'
return int(ret)
def compare_key(file):
file = file.lower().replace('.jpg', '').replace('dscf', '')
try:
return int(file)
except ValueError:
return toint(file)
#files are temporarily placed in a folder
#to prevent clashing filenames
i = 0
files = os.listdir(path)
files = (f for f in files if f.lower().endswith('.jpg'))
files = sorted(files, key=compare_key)
for file in files:
i += 10
if debug: print('renaming %s to %s.jpg' % (file, i))
os.renames(file, 'renaming/%s.jpg' % i)
for root, __, files in os.walk(path + '/renaming'):
for file in files:
if debug: print('moving %s to %s' % (root+'/'+file, path+'/'+file))
os.renames(root+'/'+file, path+'/'+file)
Edit: I got rid of all the jpg fluff. You could use this code to rename your files. Just change the rename_file function to get rid of the extra dots. I haven't tested this code so there is a possibility that it might not work.
import sys, os
path = sys.argv[1]
def rename_file(file):
return file
#files are temporarily placed in a folder
#to prevent clashing filenames
files = os.listdir(path)
for file in files:
os.renames(file, 'renaming/' + rename_file(file))
for root, __, files in os.walk(path + '/renaming'):
for file in files:
os.renames(root+'/'+file, path+'/'+file)
Looks like I just needed to set the default directory and it worked just fine.
folder = r"blah\blah\blah"
os.chdir(folder)
for filename in os.listdir(folder):
fcount = filename.count('.') - 1
newname = filename.replace('.', ' ', fcount)
os.rename(filename, newname)

Python: Using shutil.move or os.rename to move folders

I have written a script to move video files from one directory to another, it will also search sub directories using os.walk. however if the script finds a video file it will only move the file and not the containing folder. i have added an if statement to check if the containing folder is different to the original search folder.
i cant find the code to actually move(or rename?) the folder and file to a different directory. i have read/watch a lot on moving files and there is a lot of information on that, but i cant find anything for moving folders.
i have tried using shutil.move and os.rename and i get an error both times. when i try and search for the problem i get a lot of results about how to move files, or how to change the current working directory of python.
any advice(even how to phrase the google search to accuratly describe how to find a tutorial on the subject) would be really appreciated. it's my first real world python program and ive learnt a lot but this last step is wearing me down!
EDIT: when trying to use os.rename(src_file, dst_file) i get the error WindowsError: error 3 The system cannot find the path specified.
when trying shutil.move(src_file, dst_file) i get ioerror errno 2 no such file or directory "H:\\Moviesfrom download...\OneOfTheVideoFilesNotInParentFolder ie the folder and the file needs to move.
thanks.
ps like i said it's my first script outside of code academy so any random suggestions would also be appreciated.
import os
import shutil
import time
movietypes = ('.3gp', '.wmv', '.asf', '.avi', '.flv', '.mov', '.mp4', '.ogm', '.mkv',
'. mpg', '.mpg', '.nsc', '.nsv', '.nut', '.a52', '.tta', '.wav', '.ram', '.asf',
'.wmv', '. ogg', '.mka', '.vid', '.lac', '.aac', '.dts', '.tac',
'.dts', '.mbv')
filewrite = open('H:\\Movies from download folder\\Logs\\logstest.txt', 'w')
dir_src = "C:\\Users\\Jeremy\\Downloads\\"
dir_dst = "H:\\Movies from download folder\\"
for root, dirs, files in os.walk(dir_src):
for file in files:
if file.endswith(movietypes) == True:
filestr = str(file)
locationoffoundfile = os.path.realpath(os.path.join(root,filestr))
folderitwasin = locationoffoundfile.replace(dir_src,'')
folderitwasin = folderitwasin.replace(filestr,'')
pathofdir = os.path.realpath(root) + "\\"
if pathofdir != dir_src:
src_file = locationoffoundfile
dst_file = dir_dst + folderitwasin + filestr
os.rename(src_file, dst_file) #****This line is the line im having issues with***
print src_file
print dst_file
filewrite.write(file + " " + "needs to have dir and file moved Moved!" + '\n')
else:
src_file = os.path.join(dir_src, file)
dst_file = os.path.join(dir_dst, file)
print src_file
print dst_file
shutil.move(src_file, dst_file)
filewrite.write(os.path.dirname(file) + '\n')
filewrite.write(file + " " + "needs to have file moved Moved!" + '\n')
filewrite.close()
Looks like you're only moving files, without doing anything about the folders. So if you try to move
C:\Users\Jeremy\Downloads\anime\pokemon.avi
to
H:\Movies from download folder\anime\pokemon.avi
it will fail because there's no anime directory on H:\ yet.
Before iterating through files, iterate through dirs to ensure that the directory exists at your destination, creating it if necessary.
for root, dirs, files in os.walk(dir_src):
for dir in dirs:
dest_dir = os.path.join(dir_dst, dir)
if not os.path.isdir(dest_dir):
os.mkdir(dest_dir)
for file in files:
#rest of code goes here as usual...
As these are MS Windows paths use forward slashes instead and declare path as a string literal; e.g.
dir_dst = r"H:/Movies from download folder/"

Categories