Bash, getting the latest folder based on its name

2019-09-05 00:45发布

问题:

Can anyone tell me how to get the name of the latest folder based on its name which is formatted as a date, using bash. For example:

20161121/
20161128/
20161205/
20161212/

The output should be: 20161212

回答1:

Just use GNU sort with -nr flags for based on reverse numerical sort.

find . ! -path . -type d | sort -nr | head -1

An example structure, I have a list of following folders in my current path,

find . ! -path . -type d 
./20161121
./20161128
./20161205
./20161212

See how the sort picks up the folder you need,

find . ! -path . -type d | sort -nr
./20161212
./20161205
./20161128
./20161121

and head -1 for first entry alone,

find . ! -path . -type d | sort -nr | head -1
./20161212

to store it in a variable, use command-substitution $() as

myLatestFolder=$(find . ! -path . -type d | sort -nr | head -1)


回答2:

Sorting everything seems like extra work if all you want is a single entry. It could especially be problematic if you need to sort a very large number of entries. Plus, you should note that find-based solutions will by default traverse subdirectories, which might or might not be what you're after.

$ shopt -s extglob
$ mkdir 20160110 20160612 20160614 20161120
$ printf '%d\n' 20+([0-9]) | awk '$1>d{d=$1} END{print d}'
20161120
$

While the pattern 20+([0-9]) doesn't precisely match dates (it's hard to validate dates without at least a couple of lines of code), we've at least got a bit of input validation via printf, and a simple "print the highest" awk one-liner to parse printf's results.

Oh, also, this handles any directory entries that are named appropriately, and does not validate that they are themselves directories. That too would require either an extra test or a different tool.

One method to require items to be directories would be the use of a trailing slash:

$ touch 20161201
$ printf '%s\n' 20+([0-9])/ | awk '$1>d{d=$1} END{print d}'
20161120/

But that loses the input validation (the %d format for printf).

If you felt like it, you could build a full pattern for your directory names though:

$ dates='20[01][0-9][01][0-9][0-3][0-9]'
$ printf '%s\n' $dates/ | awk '$1>d{d=$1} END{print d}'
20161120/