132

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?

2
  • 2
    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 with sed 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 :) Commented Apr 16, 2016 at 6:39
  • Damn, I was hoping that I wouldn't have to use -l but retain the date info. Commented Nov 9, 2022 at 21:20

14 Answers 14

155

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.

6
  • 3
    This is nice, but it does have the "environment too large" /"argument list too long" problem potentially.
    – Mat
    Commented Oct 7, 2011 at 7:02
  • 6
    :-) Just a proof of concept. In Real Life[tm] this will be a find . -type f -print0 | xargs -0 stat -c "%y %s %n"
    – f4m8
    Commented Oct 13, 2011 at 7:27
  • 5
    To format the output of 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
  • Because with ls I can output it with a thousand separator char. How does it work with stat? Commented Mar 17, 2018 at 15:43
  • 5
    That command seems to be for GNU stat. For MacOS/BSD, the command is stat -f "%m %z %N" [files...]. Commented Jan 8, 2019 at 14:50
48

You could always use another utility like awk to format the output of ls1:

/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...

7
  • That doesn't print the file size though. And it only prints the first part of filenames with whitespace in them. And it can fail if 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
    Commented Oct 7, 2011 at 6:16
  • I had the file size in there and then edited it out (vague moment) - I'll restore it. And I agree about all the caveats re parsing ls, but that is what the OP wanted...
    – jasonwryan
    Commented Oct 7, 2011 at 6:31
  • I disagree, the OP wants the filenames, not the first part of filenames if the filename happens to have whitespace. (Using /bin/ls would avoid the alias problem.)
    – Mat
    Commented Oct 7, 2011 at 6:34
  • 1
    love this solution; in regards to previous comments about not printing size, you can get size with ls, and can use -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? ;)
    – abgordon
    Commented Jan 24, 2019 at 20:34
  • 1
    This still doesn't show the size or the filename, not even a chunk of the latter. And if --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
    Commented Aug 29, 2022 at 22:12
38

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.

4
  • 1
    Above input to find ('%CY%Cm%Cd.%C...') is long. At least GNU find has %C+ (output "2016-08-29+10:57:56.9201257840") and %Cc (output "Mo 29 Aug 2016 10:57:56 CEST")
    – guettli
    Commented Dec 1, 2016 at 9:47
  • 1
    Wish this worked on macs.
    – Jerinaw
    Commented Jul 17, 2018 at 17:31
  • 1
    lovely, and if you want to print just the full path and size, this should work "find /path/to/ -printf '%h/%f %s\n'" Commented Sep 28, 2018 at 8:06
  • @Jerinaw It works for me on MacOS Catalina, bash terminal. Commented Sep 29, 2020 at 3:41
9

You can also use the 'date' command. It is very easy to use:

date -r [file name]

1
  • Nice, this was new to me. Unfortunately it does not work for several files via globbing: date -r foo*.txt --> date: extra operand "foo2.txt"
    – guettli
    Commented Dec 1, 2016 at 9:38
9

If you wish to use ls, but preserve proper size, you can use:

ls -Ss1pq --block-size=1
1
  • Not sure why you added Spq options, can you elaborate?
    – karfau
    Commented Mar 3, 2021 at 14:27
5

ls -s1 returns file size and name only on AIX, not sure about Linux

4
  • 4
    Can you explain how/why you believe this answers the question? Commented Jun 13, 2017 at 20:04
  • 1
    Best answer here. This works very well cross-platform. MacOS, Alpine Linux... @Scott man ls and click the Edit button here, Chief. Commented May 6, 2022 at 18:08
  • This works on Solaris 10 as well - elegant, simple solution.
    – SAFX
    Commented Jul 8, 2023 at 19:17
  • 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
4

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-

Explanation

  • 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 one
  • cut -d' ' -f5-: get from the 5th column to the end, which in this case is size, date, filename (and the usual -> target for symlinks).

Caveats

  • This solution assumes there are no space or newline characters in your filenames.
  • For flexibility in output column ordering, consider one of the solutions that uses awk.
2
  • This is useful. It's the only answer that I found working in a Busybox environment, where a lot of other commands are not available or have less options. I needed to adapt it slightly, I used ls -lR --full-time | tr -s ' ' | cut -d" " -f5-
    – Kar.ma
    Commented Jan 20, 2023 at 8:45
  • 1
    It also assumes usernames and groups don't contain spaces in their names. In environments where these are managed externally it's a possibility you might need to consider Commented Dec 16, 2023 at 23:20
0

where space is defined as the separator and f6 means field 6

ls -lt | cut -d" " -f6-
1
  • 4
    it failed because ls uses spaces for indentation and sometimes it is -f6- other times it is -f5- Commented Apr 16, 2016 at 6:37
0

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.

0

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...

0

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.

0

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
0

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
-1

You can pipeline two commands

ls -l|cut -d" " -f5
1
  • 2
    it failed because ls uses spaces for indentation and sometimes it is -f6- other times it is -f5- Commented Apr 16, 2016 at 6:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .