Moving specific file types with Python - python

I know this is going to be frustratingly easy for many of you. I am just beginning to learn Python and need help with some basic file handling.
I take a lot of screenshots, which end up on my desktop (as this is the default setting). I am aware I can change the screenshot setting to save it somewhere else automatically. However, I think this program will be a good way to teach me how to sort files. I would like to use python to automatically sort through all the files on my desktop, identify those that end with .png (the default file type for screenshots), and simply move it to a folder I've named "Archive".
This is what I've got so far:
import os
import shutil
source = os.listdir('/Users/kevinconnell/Desktop/Test_Folder/')
destination = 'Archive'
for files in source:
if files.endswith('.png'):
shutil.move(source, destination)
I've played around with it plenty to no avail. In this latest version, I am encountering the following error when I run the program:
Traceback (most recent call last):
File "pngmove_2.0.py", line 23, in
shutil.move(source, destination)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/shutil.py", line 290, in move
TypeError: coercing to Unicode: need string or buffer, list found
I am under the impression I have a sort of issue with the proper convention/syntax necessary for the source and destination. However, I've thus far been unable to find much help on how to fix it. I used os.path.abspath() to determine the file path you see above.
Thanks in advance for any help in preserving my sanity.
LATEST UPDATE
I believe I am very close to getting to the bottom of this. I'm sure if I continue to play around with it I'll figure it out. Just so everyone that's been helping me is updated...
This is the current code I'm working with:
import os
import shutil
sourcepath ='/Users/kevinconnell/Desktop/'
source = os.listdir(sourcepath)
destinationpath = '/Users/kevinconnell/Desktop/'
for files in source:
if files.endswith('.png'):
shutil.move(os.path.join(sourcepath,'Test_Folder'), os.path.join(destinationpath,'Archive'))
This works for renaming my 'Test_Folder' folder to 'Archive'. However, it moves all the files in the folder, instead of moving the files that end with '.png'.

You're trying to move the whole source folder, you need to specify a file path
import os
import shutil
sourcepath='C:/Users/kevinconnell/Desktop/Test_Folder/'
sourcefiles = os.listdir(sourcepath)
destinationpath = 'C:/Users/kevinconnell/Desktop/Test_Folder/Archive'
for file in sourcefiles:
if file.endswith('.png'):
shutil.move(os.path.join(sourcepath,file), os.path.join(destinationpath,file))

Another option is using glob module, which let's you specify file mask and retrieve list of desired files.
It should be as simple as
import glob
import shutil
# I prefer to set path and mask as variables, but of course you can use values
# inside glob() and move()
source_files='/Users/kevinconnell/Desktop/Test_Folder/*.png'
target_folder='/Users/kevinconnell/Dekstop/Test_Folder/Archive'
# retrieve file list
filelist=glob.glob(source_files)
for single_file in filelist:
# move file with full paths as shutil.move() parameters
shutil.move(single_file,target_folder)
Nevertheless, if you're using glob or os.listdir, remember to set full paths for source file and target.

Based on #Gabriels answer.
I have put some effort into this as, I like to "Categorize" my file types into folders. I now use this.
I believe this is what you are looking for, this was fun to figure out
This Script:
Shows Example files to be moved until you uncomment shutil.move
Is in Python3
Was Designed On a MacOSX
Will not create folders for you, it will throw an error
Can find and move files with extension you desire
Can be used to Ignore folders
Including the destination folder, should it be nested in your search folder
Can be found in my Github Repo
Example from Terminal:
$ python organize_files.py
filetomove: /Users/jkirchoff/Desktop/Screen Shot 2018-05-15 at 12.16.21 AM.png
movingfileto: /Users/jkirchoff/Pictures/Archive/Screen Shot 2018-05-15 at 12.16.21 AM.png
Script:
I named organize_files.py
#!/usr/bin/env python3
# =============================================================================
# Created On : MAC OSX High Sierra 10.13.4 (17E199)
# Created By : Jeromie Kirchoff
# Created Date: Mon May 14 21:46:03 PDT 2018
# =============================================================================
# Answer for: https://stackoverflow.com/a/23561726/1896134 PNG Archive
# NOTE: THIS WILL NOT CREATE THE DESTINATION FOLDER(S)
# =============================================================================
import os
import shutil
file_extensn = '.png'
mac_username = 'jkirchoff'
search_dir = '/Users/' + mac_username + '/Desktop/'
target_foldr = '/Users/' + mac_username + '/Pictures/Archive/'
ignore_fldrs = [target_foldr,
'/Users/' + mac_username + '/Documents/',
'/Users/' + mac_username + '/AnotherFolder/'
]
for subdir, dirs, files in os.walk(search_dir):
for file in files:
if subdir not in ignore_fldrs and file.endswith(file_extensn):
# print('I would Move this file: ' + str(subdir) + str(file)
# # + "\n To this folder:" + str(target_foldr) + str(file)
# )
filetomove = (str(subdir) + str(file))
movingfileto = (str(target_foldr) + str(file))
print("filetomove: " + str(filetomove))
print("movingfileto: " + str(movingfileto))
# =================================================================
# IF YOU ARE HAPPY WITH THE RESULTS
# UNCOMMENT THE SHUTIL TO MOVE THE FILES
# =================================================================
# shutil.move(filetomove, movingfileto)
pass
elif file.endswith(file_extensn):
# print('Theres no need to move these files: '
# + str(subdir) + str(file))
pass
else:
# print('Theres no need to move these files either: '
# + str(subdir) + str(file))
pass

import os
import shutil
Folder_Target = input("Path Target which Contain The File Need To Move it: ")
File_Extension = input("What Is The File Extension ? [For Example >> pdf , txt , exe , ...etc] : ")
Folder_Path = input("Path To Move in it : ")
Transformes_Loges = input("Path To Send Logs Of Operation in : ")
x=0
file_logs=open(Transformes_Loges+"\\Logs.txt",mode="a+")
for folder, sub_folder, file in os.walk(Folder_Target):
for sub_folder in file:
if os.path.join(folder, sub_folder)[-3:]==File_Extension:
path= os.path.join(folder, sub_folder)
file_logs.write(path+" ===================== Was Moved to ========================>> "+Folder_Path )
file_logs.write("\n")
shutil.move(path, Folder_Path)
x+=1
file_logs.close()
print("["+str(x)+"]"+"File Transformed")

Related

How do i iterate through a directory, and print out the file names and their sizes and make the printout clean looking?

The code i am currently working on, enters a directory. Once in that directory I need to iterate through the files in that directory and print the file names and extensions, along with the file size.
os.chdir(Path('pets', 'cats'))
current = Path.cwd()
for file in os.listdir(current):
fileName = os.path.split(file)
fileSize = os.path.getsize(file)
print(str(fileName) + ': ' + str(fileSize))
The issue I am having is that the printout includes ('' '<filename.ext>'). I want to omit all these extra characters and just have <filename.ext>. Any clues on how I can clean this up?
It looks like you're using the pathlib module, so you can write:
import os
from pathlib import Path
path = Path('dogs', 'cats')
for item in path.iterdir():
if not item.is_file():
continue
fstat = os.stat(item)
print(f'{item.name}: {fstat.st_size}')
This would yield output like:
foo.txt: 32
bar.txt: 64
You could use this piece of code for the task:
import glob
import os
folPath = r'dir_address'
for fPath in glob.glob("{0}\**\*".format(folPath), recursive=True):
# get file size
fSize = os.stat(fPath).st_size/1024
print('size of {0} is {1}'.format(fPath, fSize))
I hope this helps you.

FileNotFoundError when trying to use os.rename

I've tried to write some code which will rename some files in a folder - essentially, they're listed as xxx_(a).bmp whereas they need to be xxx_a.bmp, where a runs from 1 to 2000.
I've used the inbuilt os.rename function to essentially swap them inside of a loop to get the right numbers, but this gives me FileNotFoundError [WinError2] the system cannot find the file specified Z:/AAA/BBB/xxx_(1).bmp' -> 'Z:/AAA/BBB/xxx_1.bmp'.
I've included the code I've written below if anyone could point me in the right direction. I've checked that I'm working in the right directory and it gives me the directory I'm expecting so I'm not sure why it can't find the files.
import os
n = 2000
folder = r"Z:/AAA/BBB/"
os.chdir(folder)
saved_path = os.getcwd()
print("CWD is" + saved_path)
for i in range(1,n):
old_file = os.path.join(folder, "xxx_(" + str(i) + ").bmp")
new_file = os.path.join(folder, "xxx_" +str(i)+ ".bmp")
os.rename(old_file, new_file)
print('renamed files')
The problem is os.rename doesn't create a new directory if the new name is a filename in a directory that does not currently exist.
In order to create the directory first, you can do the following in Python3:
os.makedirs(dirname, exist_ok=True)
In this case dirname can contain created or not-yet-created subdirectories.
As an alternative, one may use os.renames, which handles new and intermediate directories.
Try iterating files inside the directory and processing the files that meet your criteria.
from pathlib import Path
import re
folder = Path("Z:/AAA/BBB/")
for f in folder.iterdir():
if '(' in f.name:
new_name = f.stem.replace('(', '').replace(')', '')
# using regex
# new_name = re.sub('\(([^)]+)\)', r'\1', f.stem)
extension = f.suffix
new_path = f.with_name(new_name + extension)
f.rename(new_path)

How do i copy files with shutil in python

im trying to copy a .txt file from one dest to another. This code is running but the file isnt copying. What am i doing wrong?
import shutil
import os
src = "/c:/users/mick/temp"
src2 = "c:/users/mick"
dst = "/c:/users/mick/newfolder1/"
for files in src and src2:
if files.endswith(".txt"):
shutil.copy(files, dst)
Your for loop isn't actually searching through the files of each of your sources. In addition your for loop isn't looping through each of the sources but rather the letters in src and src2 that are present in both. This adjustment should handle what you need.
import os
src = ["c:/users/mick/temp", "c:/users/mick"]
dst = "c:/users/mick/newfolder1/"
for source in src:
for src_file in os.listdir(source):
if src_file.endswith(".txt"):
old_path = os.path.join(source, src_file)
new_path = os.path.join(dst, src_file)
os.rename(old_path, new_path)
You shouldn't need shutil for this situation as it is simply a more powerful os.rename that attempts to handle different scenarios a little better (to my knowledge). However if "newfolder1" isn't already existant than you will want to replace os.rename() with os.renames() as this attempts to create the directories inbetween.
shutils is useful for copying, but to move a file use
os.rename(oldpath, newpath)
I know the question is little older. But Here are the simple way to achieve your task. You may change the file extension as you wish. For copying you may use copy() & for moving yo may change it to move(). Hope this helps.
#To import the modules
import os
import shutil
#File path list atleast source & destination folders must be present not everything.
#*******************************WARNING**********************************************
#Make sure these folders names are already created while using the 'move() / copy()'*
#************************************************************************************
filePath1 = 'C:\\Users\\manimani\\Downloads' #Downloads folder
filePath2 = 'F:\\Projects\\Python\\Examples1' #Downloads folder
filePath3 = 'C:\\Users\\manimani\\python' #Python program files folder
filePath4 = 'F:\\Backup' #Backup folder
filePath5 = 'F:\\PDF_Downloads' #PDF files folder
filePath6 = 'C:\\Users\\manimani\\Videos' #Videos folder
filePath7 = 'F:\\WordFile_Downloads' #WordFiles folder
filePath8 = 'F:\\ExeFiles_Downloads' #ExeFiles folder
filePath9 = 'F:\\Image_Downloads' #JPEG_Files folder
#To change the directory from where the files to look // ***Source Directory***
os.chdir(filePath8)
#To get the list of files in the specific source directory
myFiles = os.listdir()
#To move all the '.docx' files to a different location // ***Destination Directory***
for filename in myFiles:
if filename.endswith('.docx'):
print('Moving the file : ' + filename)
shutil.move(filename, filePath4) #Destination directory name
print('All the files are moved as directed. Thanks')
import os, shutil
src1 = "c:/users/mick/temp/"
src2 = "c:/users/mick/"
dist = "c:/users/mick/newfolder"
if not os.path.isdir(dist) : os.mkdir(dist)
for src in [src1, src2] :
for f in os.listdir(src) :
if f.endswith(".txt") :
#print(src) # For testing purposes
shutil.copy(src, dist)
os.remove(src)
I think the error was that you were trying to copy a directory as a file, but you forgot to go through the files in the directory. You were just doing shutil.copy("c:/users/mick/temp/", c:/users/mick/newfolder/").

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/"

How to extract a file within a folder within a zip?

I need to extract a file called Preview.pdf from a folder called QuickLooks inside of a zip file.
Right now my code looks a little like this:
with ZipFile(newName, 'r') as newName:
newName.extract(\QuickLooks\Preview.pdf)
newName.close()
(In this case, newName has been set equal to the full path to the zip).
It's important to note that the backslash is correct in this case because I'm on Windows.
The code doesn't work; here's the error it gives:
Traceback (most recent call last):
File "C:\Users\Asit\Documents\Evam\Python_Scripts\pageszip.py", line 18, in <module>
ZF.extract("""QuickLooks\Preview.pdf""")
File "C:\Python33\lib\zipfile.py", line 1019, in extract
member = self.getinfo(member)
File "C:\Python33\lib\zipfile.py", line 905, in getinfo
'There is no item named %r in the archive' % name)
KeyError: "There is no item named 'QuickLook/Preview.pdf' in the archive"
I'm running the Python script from inside Notepad++, and taking the output from its console.
How can I accomplish this?
Alternatively, how could I extract the whole QuickLooks folder, move out Preview.pdf, and then delete the folder and the rest of it's contents?
Just for context, here's the rest of the script. It's a script to get a PDF of a .pages file. I know there are bonified converters out there; I'm just doing this as an excercise with some sort of real-world application.
import os.path
import zipfile
from zipfile import *
import sys
file = raw_input('Enter the full path to the .pages file in question. Please note that file and directory names cannot contain any spaces.')
dir = os.path.abspath(os.path.join(file, os.pardir))
fileName, fileExtension = os.path.splitext(file)
if fileExtension == ".pages":
os.chdir(dir)
print (dir)
fileExtension = ".zip"
os.rename (file, fileName + ".zip")
newName = fileName + ".zip" #for debugging purposes
print (newName) #for debugging purposes
with ZipFile(newName, 'w') as ZF:
print("I'm about to list names!")
print(ZF.namelist()) #for debugging purposes
ZF.extract("QuickLook/Preview.pdf")
os.rename('Preview.pdf', fileName + '.pdf')
finalPDF = fileName + ".pdf"
print ("Check out the PDF! It's located at" + dir + finalPDF + ".")
else:
print ("Sorry, this is not a valid .pages file.")
sys.exit
I'm not sure if the import of Zipfile is redundant; I read on another SO post that it was better to use from zipfile import * than import zipfile. I wasn't sure, so I used both. =)
EDIT: I've changed the code to reflect the changes suggested by Blckknght.
Here's something that seems to work. There were several issues with your code. As I mentioned in a comment, the zipfile must be opened with mode 'r' in order to read it. Another is that zip archive member names always use forward slash / characters in their path names as separators (see section 4.4.17.1 of the PKZIP Application Note). It's important to be aware that there's no way to extract a nested archive member to a different subdirectory with Python's currentzipfilemodule. You can control the root directory, but nothing below it (i.e. any subfolders within the zip).
Lastly, since it's not necessary to rename the .pages file to .zip — the filename you passZipFile() can have any extension — I removed all that from the code. However, to overcome the limitation on extracting members to a different subdirectory, I had to add code to first extract the target member to a temporary directory, and then copy that to the final destination. Afterwards, of course, this temporary folder needs to deleted. So I'm not sure the net result is much simpler...
import os.path
import shutil
import sys
import tempfile
from zipfile import ZipFile
PREVIEW_PATH = 'QuickLooks/Preview.pdf' # archive member path
pages_file = input('Enter the path to the .pages file in question: ')
#pages_file = r'C:\Stack Overflow\extract_test.pages' # hardcode for testing
pages_file = os.path.abspath(pages_file)
filename, file_extension = os.path.splitext(pages_file)
if file_extension == ".pages":
tempdir = tempfile.gettempdir()
temp_filename = os.path.join(tempdir, PREVIEW_PATH)
with ZipFile(pages_file, 'r') as zipfile:
zipfile.extract(PREVIEW_PATH, tempdir)
if not os.path.isfile(temp_filename): # extract failure?
sys.exit('unable to extract {} from {}'.format(PREVIEW_PATH, pages_file))
final_PDF = filename + '.pdf'
shutil.copy2(temp_filename, final_PDF) # copy and rename extracted file
# delete the temporary subdirectory created (along with pdf file in it)
shutil.rmtree(os.path.join(tempdir, os.path.split(PREVIEW_PATH)[0]))
print('Check out the PDF! It\'s located at "{}".'.format(final_PDF))
#view_file(final_PDF) # see Bonus below
else:
sys.exit('Sorry, that isn\'t a .pages file.')
Bonus: If you'd like to actually view the final pdf file from the script, you can add the following function and use it on the final pdf created (assuming you have a PDF viewer application installed on your system):
import subprocess
def view_file(filepath):
subprocess.Popen(filepath, shell=True).wait()

Categories