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?
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"
– f4m8
Oct 13 '11 at 07:27
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)
– LiuYan 刘研
Apr 07 '13 at 07:47
ls
I can output it with a thousand separator char. How does it work with stat
?
– Peter VARGA
Mar 17 '18 at 15:43
ls
. What about colours??
– MS Berends
Aug 08 '18 at 20:15
stat
. For MacOS/BSD, the command is stat -f "%m %z %N" [files...]
.
– Christopher Schultz
Jan 08 '19 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.
– Mat
Oct 07 '11 at 06:16
ls
, but that is what the OP wanted...
– jasonwryan
Oct 07 '11 at 06:31
/bin/ls
would avoid the alias problem.)
– Mat
Oct 07 '11 at 06:34
ls
which we both agree is not going to satisfy the whitespace requirement. The /bin/ls
suggestion is a good one.
– jasonwryan
Oct 07 '11 at 06:44
-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? ;)
ls
was explicitly asked, and awk
proposed as a solution in this response, the space in filenames problem may be solved with a similarly unadvised approach: /bin/ls -lt | awk '{printf $5};{$1=$2=$3=$4=$5=$6=$7=$8=""};{print $0}'
(macos /bin/ls, /usr/bin/awk, zsh)
– Rich Andrews
Jul 08 '22 at 13:54
--time-style=long-iso
isn't given all it prints is month day year
for old files and month day time
for recent ones.
– tink
Aug 29 '22 at 22:12
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")
– guettli
Dec 01 '16 at 09:47
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"
– guettli
Dec 01 '16 at 09:38
ls -s1 returns file size and name only on AIX, not sure about Linux
man ls
and click the Edit button here, Chief.
– Joel Mellon
May 06 '22 at 18:08
ls -s
returns the disk usage in 512 byte units (1024 byte units with GNU/busybox ls
), not the size.
– Stéphane Chazelas
Dec 18 '23 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-
– Kar.ma
Jan 20 '23 at 08:45
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
where space is defined as the separator and f6 means field 6
ls -lt | cut -d" " -f6-
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 :) – Aquarius Power Apr 16 '16 at 06:39-l
but retain the date info. – Sridhar Sarnobat Nov 09 '22 at 21:20