Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I store backups of databases in a directory structure

year/month/day/time/backup_name

an example would be

basics_mini/2012/11/05/012232/RATIONAL.0.db2inst1.NODE0000.20110505004037.001 basics_mini/2012/11/06/012251/RATIONAL.0.db2inst1.NODE0000.20110505003930.001

note that timestamp from the backup file cannot be used. Before the automation testing starts the server time is set to 5.5.2011

So the question is how I can get the latest file if I pass the "base directory" (basics_mini) to some function that I am going to code.

I need to restore the newest database. I do that in php but I wonder if there is a simple shell scripting solution.

share|improve this question
add comment

5 Answers 5

up vote 2 down vote accepted
find 'basics_mini' -type f | 
sed 's/.*basics_mini\///' |
sort -t '/' -k1nr -k2nr -k3nr -k4nr |
head -1

This will find files in your backup directory, then sed will strip the leading path (up until your year dir). Then, the sort will separate the pathname on '/' and perform a numerical sort on field 1, 2, 3 and 4, i.e., year, month, day and time. Finally, head -1 will return the top line of output.

Of course, this will only return 1 file even if there were multiple identical newest entries (if that's a concern for you).

share|improve this answer
    
Works flawlessly. Great explanation. Thank you. PS one file is good enough because it is basically imposible to have two backups created at the same time (second wise) –  Radek Nov 9 '12 at 0:26
1  
I don't see any advantage of removing the leading path with sed, nor by splitting the fields in the sort nor by sorting numericallly. nevertheless I learned how to use sort with different fields. –  miracle173 Nov 11 '12 at 8:02
    
@miracle173 The advantage being that it works in more cases than a raw sort of the input would. –  tojrobinson Nov 11 '12 at 23:54
add comment

With this naming scheme, the most recent backup is in the last subdirectory in lexicographic order. You can obtain the most recent directory directly in the shell, taking advantage of the fact that wildcards are expanded in lexicographic order.

cd basics_mini
set [0-9][0-9][0-9][0-9]/*/*/*
shift $(($#-1))
echo "The most recent backup is in $1"

In zsh, you can directly get the last directory with a glob qualifier.

echo "The most recent backup is in" basics_mini/[0-9][0-9][0-9][0-9]/*/*/*([-1])
share|improve this answer
add comment

find should suit your needs:

find "/path/to/backup_dir" -type f|sort -r|head -n1

This only works if you've got (as in your example) leading zeroes on your month and day folders

If you want a backup with a specific file name (or pattern) add a name pattern to the find parameters, e.g.

find "/path/to/backup_dir" -type f -name "*db2inst1*"|sort -r|head -n1

... or use -iname for case insensitive patterns

Now to the details of the above commands:

  • find "/path" recursively lists all files/dirs in the given path (unless you use further filtering:
  • the -type f parameter of find filters out everything that's not a regular file)
  • -name or -iname match files according to a specific pattern
  • sort sorts the output in reverse order (-r)
  • head -n1 only prints the first line (-n 1) of its input and immediately exits after doing that.
share|improve this answer
    
Somebody downvoted this answer. Why cannot you say why? –  Radek Nov 8 '12 at 23:52
3  
This will not sort the files as intended. The numeric sort is not effected at any point, let alone for each field that you want to sort by, i.e., you will get a file with month 3 being newer than one with month 10 . –  tojrobinson Nov 9 '12 at 0:25
    
You're right... @tojrobinson. But the examples in the original question all have leading zeros for months/days. So this will only become a problem in the year 10000 (as in your last example) –  mreithub Nov 9 '12 at 0:34
    
The problem will occur in October next year :-) –  Radek Nov 9 '12 at 1:07
    
@Radek: no, not in October next year, in the year 10000. –  miracle173 Nov 11 '12 at 9:17
show 4 more comments

My solution would be to use this. It will output the newest file possible:

ls -lcR --full-time | grep '^-' | sort -k 6 -r | head -n 1

Explanation:

ls -lcR

-l use a long listing format

-c show ctime (time of last modification of file status information)

-R list subdirectories recursively

grep for files starting with a - (dash), meaning 'regular-files'.

sort -k 6 -r

-k Sort by column n (6 as this holds the date field)

-r Reversed

head -n1

-n number of rows to display (from the top down. 1)

share|improve this answer
    
I don't have time to try any more. But your code doesn't work. I tried to not to 'reverse' the sort and it looked ok. –  Radek Nov 9 '12 at 0:29
    
I've moved the -r to after the -k in sort in my answer. Now it works. my fault. Changed the command without testing. silly me. –  delh Nov 9 '12 at 0:36
    
I think the -r is not necessary at all. –  Radek Nov 9 '12 at 1:06
add comment
find -maxdepth 1 -type ['d' for directory or 'f'for file] | ls -t | head -1 .. 

This should work.

share|improve this answer
    
this looks only in the current directory and avoid its sub-directories.. if you dont want that takeoff the maxdepth option –  arun Feb 27 at 18:05
    
piping find results into ls has no effect what's-so-ever, the two dots at the end also cause a syntax error, this answer simply will not run. –  X Tian Feb 28 at 0:50
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.