8

I am trying to delete oldest file in directory when number of files reaches a threshold.

list_of_files = os.listdir('log')    

if len([name for name in list_of_files]) == 25:
    oldest_file = min(list_of_files, key=os.path.getctime)
    os.remove('log/'+oldest_file)

Problem: The issue is in min method. list_of_files does not contain full path, so it is trying to search file in current directory and failing. How can I pass directory name ('log') to min()?

Elazar
  • 20,415
  • 4
  • 46
  • 67
cosmos
  • 2,263
  • 1
  • 17
  • 30

5 Answers5

17
list_of_files = os.listdir('log')
full_path = ["log/{0}".format(x) for x in list_of_files]

if len(list_of_files) == 25:
    oldest_file = min(full_path, key=os.path.getctime)
    os.remove(oldest_file)
MetaStack
  • 3,266
  • 4
  • 30
  • 67
Martin
  • 1,095
  • 9
  • 14
  • 1
    This'll work if the listdir and the log file are in the *same* place - it's better to (generally and to not repeat the use of where the file comes from) use the `os.path.abspath` to retrieve the full path name of the file and then `os.remove` that – Jon Clements Dec 10 '17 at 13:40
6

os.listdir will return relative paths - those are ones that are relative to your current/present working directory/context of what your Python script was executed in (you can see that via os.getcwd()).

Now, the os.remove function expects a full path/absolute path - shells/command line interfaces infer this and do it on your behalf - but Python doesn't. You can get that via using os.path.abspath, so you can change your code to be (and since os.listdir returns a list anyway, we don't need to add a list-comp over it to be able to check its length)...:

list_of_files = os.listdir('log')    

if len(list_of_files) >= 25:
    oldest_file = min(list_of_files, key=os.path.getctime)
    os.remove(os.path.abspath(oldest_file))

That keeps it generic as to where it came from - ie, whatever was produced in the result of os.listdir - you don't need to worry about prepending suitable file paths.

Jon Clements
  • 138,671
  • 33
  • 247
  • 280
  • Actually, this was not the issue.. os.remove correctly takes relative path (python 3.7).. The problem is inside min().. list_of_files contains only file name "abc.log" but not the relative path "log/abc.com".. so min() is unable to find key.. – cosmos Dec 10 '17 at 13:55
  • The script is being executed from parent directory of 'log' directory.. Perhaps I didn't phrase the question that way.. – cosmos Dec 10 '17 at 13:57
4

I was trying to achieve the same as what you are trying to achieve. and was facing a similar issue related to os.path.abspath() I am using a windows system with python 3.7

and the issue is that os.path.abspath() gives one folder up location replace "Yourpath" and with the path of folder in which your file is and code should work fine

import os
import time

oldest_file = sorted([ "Yourpath"+f for f in os.listdir("Yourpath")], key=os.path.getctime)[0]

print (oldest_file)
os.remove(oldest_file)
print ("{0} has been deleted".format(oldest_file))`

There must be some cleaner method to do the same I'll update when I get it

shahaf
  • 4,750
  • 2
  • 29
  • 32
ashpak
  • 74
  • 3
3

The glob library gives on the one hand full paths and allows filtering for file patterns. The above solution resulted in the directory itself as the oldest file, which is not that what I wanted. For me, the following is suitable (a blend of glob and the solution of @Ivan Motin)

import glob

sorted(glob.glob("/home/pi/Pictures/*.jpg"), key=os.path.getctime)[0]

Thomas Bobek
  • 126
  • 1
  • 8
1

using comprehension (sorry, couldn't resist):

oldest_file = sorted([os.path.abspath(f) for f in os.listdir('log') ], key=os.path.getctime)[0]
Ivan Motin
  • 21
  • 1
  • 2