How can I use ls
on Linux to get a listing of files with only their name, date, and size? I don't need to see the other info such as owner or permissions
Is this possible?
Try stat
instead of ls
. Here with the GNU implementation of stat
(beware the BSDs and zsh also have a stat
command but with a completely different API):
stat -c "%y %s %n" -- *
To output in columnar format (assuming none of the file names contain comma or newline characters):
stat -c "%n,%s" -- * | column -t -s,
Beware that if there's a file called -
in the current working directory, GNU stat
will report information about the file opened on stdin instead of for that file.
If you run into a Argument list too long
error, with shells where printf
is builtin, you can change it to:
printf '%s\0' * | xargs -0 stat -c "%y %s %n" --
Or in ksh93:
command -x stat -c "%y %s %n" -- *
Which will run as many invocations of stat
as necessary to work around the limit on the size of the arguments.
find . -type f -print0 | xargs -0 stat -c "%y %s %n"
stat
, you can add width information to the format string like C printf function, e.g. "%y %8s %n"
, it's not documented, but seems works (coreutils 8.17, Fedora 18)
Commented
Apr 7, 2013 at 7:47
ls
I can output it with a thousand separator char. How does it work with stat
?
Commented
Mar 17, 2018 at 15:43
stat
. For MacOS/BSD, the command is stat -f "%m %z %N" [files...]
.
Commented
Jan 8, 2019 at 14:50
You could always use another utility like awk
to format the output of ls
1:
/bin/ls -ls | awk '{print $7,$8,$9}'
1.Yes, generally, you shouldn't parse the output of ls but in this case the question specifically calls for it...
ls
is aliased (say alias ls='ls -i'
). You really should take a lot of care if you want to go about parsing ls output.
ls
, but that is what the OP wanted...
Commented
Oct 7, 2011 at 6:31
/bin/ls
would avoid the alias problem.)
-h
to make it human-readable. Specifically I used: ls -lah | awk '{print $5,$6,$7,$8}'
which yields: 4.0K Jan 24 18:17
. Granted, the original solution doesn't say anything about awk, but in linux we should assume the output of a process will always be the input to another process, right? ;)
--time-style=long-iso
isn't given all it prints is month day year
for old files and month day time
for recent ones.
You can get a lot of control about how you list files with the GNU implementation of the find
utility. GNU ls
doesn't really let you specify the columns you want.
For example:
$ find . -mindepth 1 -maxdepth 1 -printf '%CY%Cm%Cd.%CH%CM\t%s\t%f\n'
20111007.0601 2 b
20111001.1322 4096 a
The argument to the printf
action a detailed in the manpage. You can choose different time information, what size you want (file size or disk blocks used), etc. You can also make this safe for unusual file names if further processing is needed.
%C+
(output "2016-08-29+10:57:56.9201257840") and %Cc
(output "Mo 29 Aug 2016 10:57:56 CEST")
You can also use the 'date' command. It is very easy to use:
date -r [file name]
date -r foo*.txt
--> date: extra operand "foo2.txt"
If you wish to use ls, but preserve proper size, you can use:
ls -Ss1pq --block-size=1
ls -s1 returns file size and name only on AIX, not sure about Linux
man ls
and click the Edit button here, Chief.
Commented
May 6, 2022 at 18:08
ls -s
returns the disk usage in 512 byte units (1024 byte units with GNU/busybox ls
), not the size.
Commented
Dec 18, 2023 at 20:25
Since ls
sometimes uses multiple spaces for formatting, use tr -s' '
to squeeze down multiple spaces into a single space, so that your cut
command always refers to the same column:
ls -ln | tr -s ' ' | cut -d' ' -f5-
ls -ln
: l
flag uses "long" formatting to show permissions, ownership, size, date, etc. -n
prevents uid/gids to be converted into names which avoids problems with those containing spaces.tr -s ' '
: squeeze multiple spaces into onecut -d' ' -f5-
: get from the 5th column to the end, which in this case is size, date, filename (and the usual -> target
for symlinks).awk
.ls -lR --full-time | tr -s ' ' | cut -d" " -f5-
where space is defined as the separator and f6 means field 6
ls -lt | cut -d" " -f6-
With zsh
and its stat
builtin (which predates both GNU and BSD stat
by several years):
$ zmodload zsh/stat
$ cd /
$ for f (*) stat -LF %FT%T%z -H s -- $f && printf '%15d %s %s\n' $s[size] $s[mtime] $f
7 2021-06-27T07:13:17+0100 bin
4096 2023-12-18T09:09:13+0000 boot
3820 2023-12-18T20:01:13+0000 dev
5052 2023-12-18T20:01:19+0000 etc
52 2022-11-18T11:59:52+0000 home
29 2023-12-18T09:05:22+0000 initrd.img
29 2023-12-18T09:05:22+0000 initrd.img.old
7 2021-06-27T07:13:17+0100 lib
9 2021-06-27T07:13:17+0100 lib32
9 2021-06-27T07:13:17+0100 lib64
10 2021-06-27T07:13:17+0100 libx32
48 2022-07-11T12:22:32+0100 media
2 2023-03-24T08:52:39+0000 mnt
12 2022-03-30T15:54:13+0100 opt
0 2023-12-18T20:01:08+0000 proc
416 2023-12-13T21:17:26+0000 root
980 2023-12-18T20:03:16+0000 run
8 2021-06-27T07:13:17+0100 sbin
0 2021-06-27T07:13:26+0100 srv
0 2023-12-18T20:01:08+0000 sys
1924 2023-12-18T20:39:04+0000 tmp
116 2021-06-27T07:13:26+0100 usr
106 2023-10-01T09:09:28+0100 var
26 2023-12-18T09:05:22+0000 vmlinuz
26 2023-12-18T09:05:22+0000 vmlinuz.old
Here with with the list sorted by file name, change *
to *(om)
to sort by mtime, or *(oL)
to sort by length. %FT%T%z
here specifies the timestamp format using strftime()
style directives. You can adapt to your taste.
With the ast-open implementation of ls
:
$ ls -Z '%15(size)d %(mtime:time=%FT%T%z)s %(name)s'
7 2021-06-27T07:13:17+0100 bin
4096 2023-12-18T09:09:13-0000 boot
3820 2023-12-18T20:01:13-0000 dev
5052 2023-12-18T20:01:19-0000 etc
52 2022-11-18T11:59:52-0000 home
29 2023-12-18T09:05:22-0000 initrd.img
29 2023-12-18T09:05:22-0000 initrd.img.old
7 2021-06-27T07:13:17+0100 lib
9 2021-06-27T07:13:17+0100 lib32
9 2021-06-27T07:13:17+0100 lib64
10 2021-06-27T07:13:17+0100 libx32
48 2022-07-11T12:22:32+0100 media
2 2023-03-24T08:52:39-0000 mnt
12 2022-03-30T15:54:13+0100 opt
0 2023-12-18T20:01:08-0000 proc
416 2023-12-13T21:17:26-0000 root
980 2023-12-18T20:03:16-0000 run
8 2021-06-27T07:13:17+0100 sbin
0 2021-06-27T07:13:26+0100 srv
0 2023-12-18T20:01:08-0000 sys
1924 2023-12-18T20:48:20-0000 tmp
116 2021-06-27T07:13:26+0100 usr
106 2023-10-01T09:09:28+0100 var
26 2023-12-18T09:05:22-0000 vmlinuz
26 2023-12-18T09:05:22-0000 vmlinuz.old
As usual you can change the sort order with -t
/ -S
...
With recent versions of GNU ls
and GNU find
:
$ ls --zero | find -files0-from - -prune -printf '%15s %TF%TT%Tz %p\n'
7 2021-06-2707:13:17.6643890000+0100 bin
4096 2023-12-1809:09:13.8727765810+0000 boot
3820 2023-12-1820:01:13.8252279330+0000 dev
5052 2023-12-1820:01:19.8852276790+0000 etc
52 2022-11-1811:59:52.8691163630+0000 home
29 2023-12-1809:05:22.7943478290+0000 initrd.img
29 2023-12-1809:05:22.7943478290+0000 initrd.img.old
7 2021-06-2707:13:17.6643890000+0100 lib
9 2021-06-2707:13:17.6683890000+0100 lib32
9 2021-06-2707:13:17.6683890000+0100 lib64
10 2021-06-2707:13:17.6683890000+0100 libx32
48 2022-07-1112:22:32.7800003630+0100 media
2 2023-03-2408:52:39.4704878130+0000 mnt
12 2022-03-3015:54:13.2917948310+0100 opt
0 2023-12-1820:01:08.8172281440+0000 proc
416 2023-12-1321:17:26.0756122060+0000 root
980 2023-12-1820:03:16.1022700000+0000 run
8 2021-06-2707:13:17.6643890000+0100 sbin
0 2021-06-2707:13:26.9283890000+0100 srv
0 2023-12-1820:01:08.8172281440+0000 sys
1924 2023-12-1820:48:20.8290486240+0000 tmp
116 2021-06-2707:13:26.9403890000+0100 usr
106 2023-10-0109:09:28.9751551320+0100 var
26 2023-12-1809:05:22.7943478290+0000 vmlinuz
26 2023-12-1809:05:22.7943478290+0000 vmlinuz.old
Where ls
gets you the list of files in the order you want (add -t
to order by mtime, -S
to order by size) and find
(GNU find
4.9 or newer for -files0-from
) can be used to print the metadata you want from those files in the format you want.
With rawhide
$ LC_ALL=C rh -L '%15s %TFT%TT%Tz %f\n' -m1 -M1 -e '! ".*"'
22 2023-12-18T09:09:13+0000 boot
4 2022-11-18T11:59:52+0000 home
293 2023-12-19T08:30:09+0000 etc
4 2022-07-11T12:22:32+0100 media
12 2023-10-01T09:09:28+0100 var
7 2021-06-27T07:13:17+0100 bin
12 2021-06-27T07:13:26+0100 usr
8 2021-06-27T07:13:17+0100 sbin
7 2021-06-27T07:13:17+0100 lib
9 2021-06-27T07:13:17+0100 lib32
9 2021-06-27T07:13:17+0100 lib64
10 2021-06-27T07:13:17+0100 libx32
189 2023-12-19T07:50:10+0000 dev
382 2023-12-19T07:50:05+0000 proc
416 2023-12-13T21:17:26+0000 root
47 2023-12-19T08:30:05+0000 run
11 2023-12-19T07:50:05+0000 sys
22 2023-12-19T08:39:03+0000 tmp
1 2023-03-24T08:52:39+0000 mnt
0 2021-06-27T07:13:26+0100 srv
1 2022-03-30T15:54:13+0100 opt
26 2023-12-18T09:05:22+0000 vmlinuz.old
29 2023-12-18T09:05:22+0000 initrd.img.old
26 2023-12-18T09:05:22+0000 vmlinuz
29 2023-12-18T09:05:22+0000 initrd.img
Beware that for files of type directory, the reported size is the number of entries other than .
and ..
in them (for those file systems that still implement .
and ..
as directory entries), not the size of the directory file (unless that directory is not readable).
The format directives for -L
are generally the same as those recognised by GNU find
's -printf
predicate.
It doesn't have builtin ways to sort the file list by name/mtime/size though on a GNU system, you can use sort -z
on that output after switching to NUL-delimited records. For example, to sort by size:
$ LC_ALL=C rh -L '%15s %TFT%TT%Tz %f\0' -m1 -M1 -e '! ".*"' | sort -zn | tr '\0' '\n'
0 2021-06-27T07:13:26+0100 srv
1 2022-03-30T15:54:13+0100 opt
1 2023-03-24T08:52:39+0000 mnt
4 2022-07-11T12:22:32+0100 media
4 2022-11-18T11:59:52+0000 home
7 2021-06-27T07:13:17+0100 bin
7 2021-06-27T07:13:17+0100 lib
8 2021-06-27T07:13:17+0100 sbin
9 2021-06-27T07:13:17+0100 lib32
9 2021-06-27T07:13:17+0100 lib64
10 2021-06-27T07:13:17+0100 libx32
11 2023-12-19T07:50:05+0000 sys
12 2021-06-27T07:13:26+0100 usr
12 2023-10-01T09:09:28+0100 var
22 2023-12-18T09:09:13+0000 boot
22 2023-12-19T08:39:03+0000 tmp
26 2023-12-18T09:05:22+0000 vmlinuz
26 2023-12-18T09:05:22+0000 vmlinuz.old
29 2023-12-18T09:05:22+0000 initrd.img
29 2023-12-18T09:05:22+0000 initrd.img.old
47 2023-12-19T08:30:05+0000 run
189 2023-12-19T07:50:10+0000 dev
293 2023-12-19T08:30:09+0000 etc
386 2023-12-19T07:50:05+0000 proc
416 2023-12-13T21:17:26+0000 root
Portably, you can always use perl
:
$ perl -MPOSIX -e '
for (<*>) {
if (@s = lstat) {
printf "%15s %s %s\n", $s[7], strftime("%FT%T%z", localtime$s[9]), $_
} else {
warn "$_: $!\n"
}
}'
7 2021-06-27T07:13:17+0100 bin
4096 2023-12-18T09:09:13+0000 boot
3820 2023-12-18T20:01:13+0000 dev
5052 2023-12-18T20:01:19+0000 etc
52 2022-11-18T11:59:52+0000 home
29 2023-12-18T09:05:22+0000 initrd.img
29 2023-12-18T09:05:22+0000 initrd.img.old
7 2021-06-27T07:13:17+0100 lib
9 2021-06-27T07:13:17+0100 lib32
9 2021-06-27T07:13:17+0100 lib64
10 2021-06-27T07:13:17+0100 libx32
48 2022-07-11T12:22:32+0100 media
2 2023-03-24T08:52:39+0000 mnt
12 2022-03-30T15:54:13+0100 opt
0 2023-12-18T20:01:08+0000 proc
416 2023-12-13T21:17:26+0000 root
980 2023-12-18T20:03:16+0000 run
8 2021-06-27T07:13:17+0100 sbin
0 2021-06-27T07:13:26+0100 srv
0 2023-12-18T20:01:08+0000 sys
1924 2023-12-18T20:39:04+0000 tmp
116 2021-06-27T07:13:26+0100 usr
106 2023-10-01T09:09:28+0100 var
26 2023-12-18T09:05:22+0000 vmlinuz
26 2023-12-18T09:05:22+0000 vmlinuz.old
To sort based on other criteria such as size (like with ls -S
):
$ perl -MPOSIX -e '
for (<*>) {
if (@s = lstat) {
push @f, [$_, @s]
} else {
warn "$_: $!\n"
}
};
for (sort {$a->[8] <=> $b->[8]} @f) {
printf "%15s %s %s\n", $_->[8], strftime("%FT%T%z", localtime$_->[10]), $_->[0]
}'
0 2021-06-27T07:13:26+0100 srv
0 2023-12-18T20:01:08-0000 proc
0 2023-12-18T20:01:08-0000 sys
2 2023-03-24T08:52:39-0000 mnt
7 2021-06-27T07:13:17+0100 bin
7 2021-06-27T07:13:17+0100 lib
8 2021-06-27T07:13:17+0100 sbin
9 2021-06-27T07:13:17+0100 lib32
9 2021-06-27T07:13:17+0100 lib64
10 2021-06-27T07:13:17+0100 libx32
12 2022-03-30T15:54:13+0100 opt
26 2023-12-18T09:05:22-0000 vmlinuz
26 2023-12-18T09:05:22-0000 vmlinuz.old
29 2023-12-18T09:05:22-0000 initrd.img
29 2023-12-18T09:05:22-0000 initrd.img.old
48 2022-07-11T12:22:32+0100 media
52 2022-11-18T11:59:52-0000 home
106 2023-10-01T09:09:28+0100 var
116 2021-06-27T07:13:26+0100 usr
416 2023-12-13T21:17:26-0000 root
980 2023-12-18T20:03:16-0000 run
1924 2023-12-18T20:48:20-0000 tmp
3820 2023-12-18T20:01:13-0000 dev
4096 2023-12-18T09:09:13-0000 boot
5052 2023-12-18T20:01:19-0000 etc
You can pipeline two commands
ls -l|cut -d" " -f5
ls
is great because it has very fast sorting by datetime, but the formatting is hard to deal with. I suggest using a token at --time-style like--time-style='+&%Y%m%d+%H%M%S.%N'
where the token is '&', using that as reference you can further parse the output withsed
so you can also backtrack as just before the token is the size! If someone want to post that as a complete answer, feel free to, I am too asleep right now :)-l
but retain the date info.