1

Doing

glob.glob('/var/log/apache2/other_vhosts_access.log*')

gives an unsorted list such as ['....76.gz', '....16.gz', '....46.gz', ...]. Also,

sorted(glob.glob('/var/log/apache2/other_vhosts_access.log*')) 

gives

other_vhosts_access.log
other_vhosts_access.log.1
other_vhosts_access.log.10.gz
other_vhosts_access.log.11.gz
other_vhosts_access.log.12.gz
...
other_vhosts_access.log.19.gz
other_vhosts_access.log.2.gz

How to have a better sort? .log, .log.1, .log.2.gz, ..., .log.9.gz, .log.10.gz, ...

Basj
  • 41,386
  • 99
  • 383
  • 673
  • You can create your own sort key function and pass it to sorted, and the sort key could pull out the number, and return it as an int. – RufusVS Jul 15 '21 at 13:56
  • @RufusVS Yes, with `sorted(..., key=...)`, but I'm more looking for a general solution not harcoded for each situation. – Basj Jul 15 '21 at 14:11

2 Answers2

1

To expand on my comment, perhaps something like this will do. This pulls the first sequence of digits found between decimal points or at the end of the file and uses the value as the primary sort key, and the full file name for secondary.

file_list = """
other_vhosts_access.log
other_vhosts_access.log.1
other_vhosts_access.log.10.gz
other_vhosts_access.log.11.gz
other_vhosts_access.log.12.gz
other_vhosts_access.log.19.gz
other_vhosts_access.log.2.gz
""".strip().split()

import re

re_num = r"\.(\d+)(\.|$)"

def sort_key(file_name):
    match=re.search(re_num,file_name)
    if match is None:
        return(0,file_name)
    else:
        return(int(match.group(1)),file_name)
    
print(*sorted(file_list,key=sort_key),sep='\n')
RufusVS
  • 4,008
  • 3
  • 29
  • 40
  • Isn't there a generaly way without hardcoding this regex search? – Basj Jul 15 '21 at 14:29
  • 1
    I'm not sure what you mean by "general" way. Every way will have to include a way to parse the file names with some kind of rule to establish sortation order. – RufusVS Jul 15 '21 at 14:36
  • Isn't there a general "natural sort" way to do it @RufusVS? Here is how it works with `/bin/ls`: https://unix.stackexchange.com/questions/33909/list-files-sorted-numerically/33913#33913 – Basj Jul 15 '21 at 14:59
  • There are much better (more general) solutions in the link specified in the closed note and other answer. Oh! you posted that answer! – RufusVS Jul 15 '21 at 18:11
0

Based on Is there a built in function for string natural sort?, here is a one-liner solution:

natsort = lambda s: [int(t) if t.isdigit() else t.lower() for t in re.split('(\d+)', s)]

sorted(glob.glob('/var/log/apache2/other_vhosts_access.log*'), key=natsort)
Basj
  • 41,386
  • 99
  • 383
  • 673
  • This is essentially a copy of that answer. Good case for closing as a duplicate IMO – Pranav Hosangadi Jul 15 '21 at 16:50
  • Thank you for linking the duplicate @PranavHosangadi. Note: I clearly cited the original question, I didn't do it for rep, but just for completeness, so that anyone can find the solution quickly without reading the many answers there. Not sure a downvote is really useful here ;) – Basj Jul 15 '21 at 17:21
  • I love one-liners! I'll have to learn about `re.split` now! – RufusVS Jul 15 '21 at 17:29