Add y flag and environment variable LS_SAMESORT to specify the same
sorting order for time and name with the -t option. IEEE Std 1003.2 (POSIX.2) mandates that the -t option sort in descending order, and that if two files have the same timestamp, they should be sorted in ascending order of their names. The -r flag reverses both of these sort orders, so they're never the same. This creates significant problems for sequentially named files stored on FAT file systems, where it can be impossible to list them in the order in which they were created. Add , (comma) option to print file sizes grouped and separated by thousands using the non-monetary separator returned by localeconv(3), typically a comma or period. MFC after: 14 days
This commit is contained in:
parent
f8eb8ef711
commit
9aa68a3ffa
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=242725
20
bin/ls/cmp.c
20
bin/ls/cmp.c
@ -78,7 +78,10 @@ modcmp(const FTSENT *a, const FTSENT *b)
|
||||
if (b->fts_statp->st_mtim.tv_nsec <
|
||||
a->fts_statp->st_mtim.tv_nsec)
|
||||
return (-1);
|
||||
return (strcoll(a->fts_name, b->fts_name));
|
||||
if (f_samesort)
|
||||
return (strcoll(b->fts_name, a->fts_name));
|
||||
else
|
||||
return (strcoll(a->fts_name, b->fts_name));
|
||||
}
|
||||
|
||||
int
|
||||
@ -104,7 +107,10 @@ acccmp(const FTSENT *a, const FTSENT *b)
|
||||
if (b->fts_statp->st_atim.tv_nsec <
|
||||
a->fts_statp->st_atim.tv_nsec)
|
||||
return (-1);
|
||||
return (strcoll(a->fts_name, b->fts_name));
|
||||
if (f_samesort)
|
||||
return (strcoll(b->fts_name, a->fts_name));
|
||||
else
|
||||
return (strcoll(a->fts_name, b->fts_name));
|
||||
}
|
||||
|
||||
int
|
||||
@ -130,7 +136,10 @@ birthcmp(const FTSENT *a, const FTSENT *b)
|
||||
if (b->fts_statp->st_birthtim.tv_nsec <
|
||||
a->fts_statp->st_birthtim.tv_nsec)
|
||||
return (-1);
|
||||
return (strcoll(a->fts_name, b->fts_name));
|
||||
if (f_samesort)
|
||||
return (strcoll(b->fts_name, a->fts_name));
|
||||
else
|
||||
return (strcoll(a->fts_name, b->fts_name));
|
||||
}
|
||||
|
||||
int
|
||||
@ -156,7 +165,10 @@ statcmp(const FTSENT *a, const FTSENT *b)
|
||||
if (b->fts_statp->st_ctim.tv_nsec <
|
||||
a->fts_statp->st_ctim.tv_nsec)
|
||||
return (-1);
|
||||
return (strcoll(a->fts_name, b->fts_name));
|
||||
if (f_samesort)
|
||||
return (strcoll(b->fts_name, a->fts_name));
|
||||
else
|
||||
return (strcoll(a->fts_name, b->fts_name));
|
||||
}
|
||||
|
||||
int
|
||||
|
72
bin/ls/ls.1
72
bin/ls/ls.1
@ -32,7 +32,7 @@
|
||||
.\" @(#)ls.1 8.7 (Berkeley) 7/29/94
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd September 28, 2011
|
||||
.Dd November 8, 2012
|
||||
.Dt LS 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -40,7 +40,7 @@
|
||||
.Nd list directory contents
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl ABCFGHILPRSTUWZabcdfghiklmnopqrstuwx1
|
||||
.Op Fl ABCFGHILPRSTUWZabcdfghiklmnopqrstuwxy1,
|
||||
.Op Fl D Ar format
|
||||
.Op Ar
|
||||
.Sh DESCRIPTION
|
||||
@ -130,6 +130,8 @@ This option is equivalent to defining
|
||||
.Ev CLICOLOR
|
||||
in the environment.
|
||||
(See below.)
|
||||
This functionality can be compiled out by removing the definition of
|
||||
.Ev COLORLS .
|
||||
.It Fl H
|
||||
Symbolic links on the command line are followed.
|
||||
This option is assumed if
|
||||
@ -249,12 +251,35 @@ subsection below, except (if the long format is not also requested)
|
||||
the directory totals are not output when the output is in a
|
||||
single column, even if multi-column output is requested.
|
||||
.It Fl t
|
||||
Sort by time modified (most recently modified
|
||||
first) before sorting the operands in lexicographical
|
||||
order.
|
||||
Sort by descending time modified (most recently modified first). If two files
|
||||
have the same modification timestamp, sort their names in ascending
|
||||
lexicographical order.
|
||||
The
|
||||
.Fl r
|
||||
option reverses both of these sort orders.
|
||||
.Pp
|
||||
Note that these sort orders are contradictory: the time sequence is in
|
||||
descending order, the lexicographical sort is in ascending order.
|
||||
This behavior is mandated by
|
||||
.St -p1003.2 .
|
||||
This feature can cause problems listing files stored with sequential names on
|
||||
FAT file systems, such as from digital cameras, where it is possible to have
|
||||
more than one image with the same timestamp.
|
||||
In such a case, the photos cannot be listed in the sequence in which
|
||||
they were taken.
|
||||
To ensure the same sort order for time and for lexicographical sorting, set the
|
||||
environment variable
|
||||
.Ev LS_SAMESORT
|
||||
or use the
|
||||
.Fl y
|
||||
option.
|
||||
This causes
|
||||
.Nm
|
||||
to reverse the lexicographal sort order when sorting files with the
|
||||
same modification timestamp.
|
||||
.It Fl u
|
||||
Use time of last access,
|
||||
instead of last modification
|
||||
instead of time of last modification
|
||||
of the file for sorting
|
||||
.Pq Fl t
|
||||
or printing
|
||||
@ -268,6 +293,15 @@ The same as
|
||||
.Fl C ,
|
||||
except that the multi-column output is produced with entries sorted
|
||||
across, rather than down, the columns.
|
||||
.It Fl y
|
||||
When the
|
||||
.Fl t
|
||||
option is set, sort the alphabetical output in the same order as the time output.
|
||||
This has the same effect as setting
|
||||
.Ev LS_SAMESORT .
|
||||
See the description of the
|
||||
.Fl t
|
||||
option for more details.
|
||||
.It Fl 1
|
||||
(The numeric digit
|
||||
.Dq one . )
|
||||
@ -275,6 +309,15 @@ Force output to be
|
||||
one entry per line.
|
||||
This is the default when
|
||||
output is not to a terminal.
|
||||
.It Fl ,
|
||||
(Comma) When the
|
||||
.Fl l
|
||||
option is set, print file sizes grouped and separated by thousands using the
|
||||
non-monetary separator returned by
|
||||
.Xr localeconv 3 ,
|
||||
typically a comma or period.
|
||||
If no locale is set, or the locale does not have a non-monetary separator, this
|
||||
option has no effect.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
@ -529,7 +572,7 @@ variable is defined.
|
||||
.It Ev CLICOLOR_FORCE
|
||||
Color sequences are normally disabled if the output is not directed to
|
||||
a terminal.
|
||||
This can be overridden by setting this flag.
|
||||
This can be overridden by setting this variable.
|
||||
The
|
||||
.Ev TERM
|
||||
variable still needs to reference a color capable terminal however
|
||||
@ -655,6 +698,14 @@ Not all columns have changeable widths.
|
||||
The fields are,
|
||||
in order: inode, block count, number of links, user name,
|
||||
group name, flags, file size, file name.
|
||||
.It Ev LS_SAMESORT
|
||||
If this variable is set, the
|
||||
.Fl t
|
||||
option sorts the names of files with the same modification timestamp in the same
|
||||
sense as the time sort.
|
||||
See the description of the
|
||||
.Fl t
|
||||
option for more details.
|
||||
.It Ev TERM
|
||||
The
|
||||
.Ev CLICOLOR
|
||||
@ -678,6 +729,7 @@ specification.
|
||||
.Xr getfacl 1 ,
|
||||
.Xr sort 1 ,
|
||||
.Xr xterm 1 ,
|
||||
.Xr localeconv 3 ,
|
||||
.Xr strftime 3 ,
|
||||
.Xr strmode 3 ,
|
||||
.Xr termcap 5 ,
|
||||
@ -716,3 +768,9 @@ option description might be a feature that was
|
||||
based on the fact that single-column output
|
||||
usually goes to something other than a terminal.
|
||||
It is debatable whether this is a design bug.
|
||||
.Pp
|
||||
.St -p1003.2
|
||||
mandates opposite sort orders for files with the same timestamp when
|
||||
sorting with the
|
||||
.Fl t
|
||||
option.
|
||||
|
25
bin/ls/ls.c
25
bin/ls/ls.c
@ -109,10 +109,11 @@ int termwidth = 80; /* default terminal width */
|
||||
int f_humanval; /* show human-readable file sizes */
|
||||
int f_inode; /* print inode */
|
||||
static int f_kblocks; /* print size in kilobytes */
|
||||
int f_label; /* show MAC label */
|
||||
static int f_listdir; /* list actual directory, not contents */
|
||||
static int f_listdot; /* list files beginning with . */
|
||||
static int f_noautodot; /* do not automatically enable -A for root */
|
||||
int f_longform; /* long listing format */
|
||||
static int f_noautodot; /* do not automatically enable -A for root */
|
||||
static int f_nofollow; /* don't follow symbolic link arguments */
|
||||
int f_nonprint; /* show unprintables as ? */
|
||||
static int f_nosort; /* don't sort output */
|
||||
@ -122,19 +123,21 @@ static int f_numericonly; /* don't convert uid/gid to name */
|
||||
int f_octal_escape; /* like f_octal but use C escapes if possible */
|
||||
static int f_recursive; /* ls subdirectories also */
|
||||
static int f_reversesort; /* reverse whatever sort is used */
|
||||
int f_sectime; /* print the real time for all files */
|
||||
int f_samesort; /* sort time and name in same direction */
|
||||
int f_sectime; /* print full time information */
|
||||
static int f_singlecol; /* use single column output */
|
||||
int f_size; /* list size in short listing */
|
||||
static int f_sizesort;
|
||||
int f_slash; /* similar to f_type, but only for dirs */
|
||||
int f_sortacross; /* sort across rows, not down columns */
|
||||
int f_statustime; /* use time of last mode change */
|
||||
static int f_stream; /* stream the output, separate with commas */
|
||||
static int f_timesort; /* sort by time vice name */
|
||||
int f_thousands; /* show file sizes with thousands separators */
|
||||
char *f_timeformat; /* user-specified time format */
|
||||
static int f_sizesort;
|
||||
static int f_timesort; /* sort by time vice name */
|
||||
int f_type; /* add type character for non-regular files */
|
||||
static int f_whiteout; /* show whiteout entries */
|
||||
int f_label; /* show MAC label */
|
||||
|
||||
#ifdef COLORLS
|
||||
int f_color; /* add type in color for non-regular files */
|
||||
|
||||
@ -180,8 +183,10 @@ main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
fts_options = FTS_PHYSICAL;
|
||||
if (getenv("LS_SAMESORT"))
|
||||
f_samesort = 1;
|
||||
while ((ch = getopt(argc, argv,
|
||||
"1ABCD:FGHILPRSTUWZabcdfghiklmnopqrstuwx")) != -1) {
|
||||
"1ABCD:FGHILPRSTUWXZabcdfghiklmnopqrstuwxy,")) != -1) {
|
||||
switch (ch) {
|
||||
/*
|
||||
* The -1, -C, -x and -l options all override each other so
|
||||
@ -237,6 +242,9 @@ main(int argc, char *argv[])
|
||||
f_sizesort = 0;
|
||||
break;
|
||||
/* Other flags. Please keep alphabetic. */
|
||||
case ',':
|
||||
f_thousands = 1;
|
||||
break;
|
||||
case 'B':
|
||||
f_nonprint = 0;
|
||||
f_octal = 1;
|
||||
@ -338,6 +346,9 @@ main(int argc, char *argv[])
|
||||
f_octal = 0;
|
||||
f_octal_escape = 0;
|
||||
break;
|
||||
case 'y':
|
||||
f_samesort = 1;
|
||||
break;
|
||||
default:
|
||||
case '?':
|
||||
usage();
|
||||
@ -850,6 +861,8 @@ display(const FTSENT *p, FTSENT *list, int options)
|
||||
d.s_size = sizelen;
|
||||
d.s_user = maxuser;
|
||||
}
|
||||
if (f_thousands) /* make space for commas */
|
||||
d.s_size += (d.s_size - 1) / 3;
|
||||
printfcn(&d);
|
||||
output = 1;
|
||||
|
||||
|
@ -49,11 +49,13 @@ extern int f_longform; /* long listing format */
|
||||
extern int f_octal; /* print unprintables in octal */
|
||||
extern int f_octal_escape; /* like f_octal but use C escapes if possible */
|
||||
extern int f_nonprint; /* show unprintables as ? */
|
||||
extern int f_samesort; /* sort time and name in same direction */
|
||||
extern int f_sectime; /* print the real time for all files */
|
||||
extern int f_size; /* list size in short listing */
|
||||
extern int f_slash; /* append a '/' if the file is a directory */
|
||||
extern int f_sortacross; /* sort across rows, not down columns */
|
||||
extern int f_statustime; /* use time of last mode change */
|
||||
extern int f_thousands; /* show file sizes with thousands separators */
|
||||
extern char *f_timeformat; /* user-specified time format */
|
||||
extern int f_notabs; /* don't use tab-separated multi-col output */
|
||||
extern int f_type; /* add type character for non-regular files */
|
||||
|
@ -606,7 +606,11 @@ printsize(size_t width, off_t bytes)
|
||||
humanize_number(buf, sizeof(buf), (int64_t)bytes, "",
|
||||
HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
|
||||
(void)printf("%*s ", (u_int)width, buf);
|
||||
} else
|
||||
} else if (f_thousands) { /* with commas */
|
||||
/* This format assignment needed to work round gcc bug. */
|
||||
const char *format = "%*j'd ";
|
||||
(void)printf(format, (u_int)width, bytes);
|
||||
} else
|
||||
(void)printf("%*jd ", (u_int)width, bytes);
|
||||
}
|
||||
|
||||
|
@ -222,9 +222,9 @@ usage(void)
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
#ifdef COLORLS
|
||||
"usage: ls [-ABCFGHILPRSTUWZabcdfghiklmnopqrstuwx1] [-D format]"
|
||||
"usage: ls [-ABCFGHILPRSTUWZabcdfghiklmnopqrstuwxy1,] [-D format]"
|
||||
#else
|
||||
"usage: ls [-ABCFHILPRSTUWZabcdfghiklmnopqrstuwx1] [-D format]"
|
||||
"usage: ls [-ABCFHILPRSTUWZabcdfghiklmnopqrstuwxy1,] [-D format]"
|
||||
#endif
|
||||
" [file ...]\n");
|
||||
exit(1);
|
||||
|
Loading…
Reference in New Issue
Block a user