tl;dr
printf '%s\n' suman-*/ | tail -n 1 | sed 's|/$||' # ... | cut -d/ -f1 works too
Note that this answer assumes that filenames don't have embedded newlines, which, fortunately, is rarely a real-world concern.
All commands in this answer are POSIX-compliant, except where noted.
If you're only looking for immediate subdirectories in your target directory, there's no need for find
- a simple glob will do:
printf '%s\n' suman-*/ | head -n 1
Note, however, that:
- this outputs subdirectory names with a trailing
/
.
- symlinks to directories are included.
- hidden subdirectories are not included (not a concern with
suman-*/
, which by definition never matches hidden dirs.) - to include hidden items in general, run shopt -s dotglob
first (this is a Bash extension).
- output sorting is case-sensitive, even though the macOS default filesystem is case-insensitive - to change that, pipe the
printf
output to sort -f
or sort -rf
before further processing.
Regarding your request to find the most recently modified directory matching the pattern, combining ls -dt
with a glob is the simplest option:
ls -dt suman-*/ | head -n 1 # print most recently modified suman-* subdir.
If, by contrast, the timestamps embedded in the directory names should drive the sorting (e.g., 1479860475524
), reverse lexical sorting will do:
ls -dr suman-*/ | head -n 1
Without the trailing /
:
ls -dr suman-*/ | head -n 1 | sed 's|/$||' # with no path prefix, | cut -d/ -f1 works too
A slightly more cumbersome, but more robust alternative that avoids use of ls
in favor of avoiding the max. command-line length when calling external utilities, as reported by getconf ARG_MAX
, which could be a concern if a large number of files match the glob: Tip of the hat to Charles Duffy.
printf '%s\n' suman-*/ | tail -n 1 | sed 's|/$||'
Note: This assumes that printf
is implemented as a shell builtin (as opposed to having to rely on the printf
utility), which, however, is true of all major POSIX-like shells (bash
, zsh
, ksh
, dash
).
Case-insensitive alternative with sort
(makes no difference in this scenario):
printf '%s\n' suman-*/ | sort -rf | head -n 1 | sed 's|/$||'
Regarding your 3 original questions:
Re 1): use sed
to trim the trailing /
: printf '%s\n' suman-*/ | head -n 1 | sed 's|/$||'
(if stripping path prefixes is also a concern, it's easiest to cd
to the path prefix first and then use a filename-only glob).
Re 2): use printf ... | tail -1 | ...
to get the lexically last entry (or printf ... | sort -rf | head -n 1 | ...
to get the lexically last entry irrespective of case).
Re 3): (globbing) patterns allow per-character-position digit matching with character sets such as [0-9]
, but you cannot apply regex-style quantifiers (duplication symbols) such as ?
and +
to them.
Generally, there are many subtle differences between using find
and globbing / ls
- caveat emptor.
Generally, parsing ls
output should be avoided, but - assuming one is aware of the edge cases and limitations - sometimes it is the most convenient solution.