78

Contents of my dir are

$ ls -lrt
total 0
-rw-r--r-- 1 user1 admin 19 Oct  8 12:31 night.txt
-rw-r--r-- 1 user1 admin 19 Oct  8 12:31 noon.txt
-rw-r--r-- 1 user1 admin 38 Oct  8 12:31 day.txt

I would like to list out details of files that have a word in the filename as specified.

Example :

$ ls -lrt *day|night*
ls: *day: No such file or directory
bash: night.txt: command not found

Expected output

-rw-r--r-- 1 user1 admin 19 Oct  8 12:31 night.txt
-rw-r--r-- 1 user1 admin 38 Oct  8 12:31 day.txt

How to list out different files matching 2 different partterns, or in short how to use regex with ls, so that I could OR the filename parts.

Original scenarion, there are many file in the directory, have shortened the case for asking.

4 Answers 4

95

You don't even need extended globbing enabled to do what you want. This will work in bash:

ls {day*,night*}
3
  • 8
    No it doesn't: touch day.txt; touch night.txt; ls {*day,night*} results in ls: *day: No such file or directory
    – Matteo
    Oct 8, 2012 at 16:46
  • 2
    I was adapting the original poster's text; I thought that was clear. sigh. Text updated. Surely you can see that the mechanism works?
    – itsbruce
    Oct 8, 2012 at 16:50
  • 11
    Or possibly *{day,night}* is closer to what the OP wants.
    – derobert
    Oct 8, 2012 at 17:24
31

There is no option in ls to filter on filename but in most of the shells there are globbing extension man bash /Pattern Matching

ksh

ls -lrtd -- *@(day|night)*

zsh

setopt extendedglob
ls -lrtd -- *(day|night)*

or:

setopt kshglob
ls -lrtd -- *@(day|night)*

bash

shopt -s extglob
ls -lrtd -- *@(day|night)*

In any of these three shells you can do this, but note that if one of the cases doesn't match any file, that pattern will be left unexpanded (e.g. *day* night1.txt othernight.txt if there is no file name containing day; see man bash /EXPANSION or /Brace Expansion specifically):

ls -lrtd -- *{day,night}*

In any shells you can do:

ls -lrtd -- *day* *night*

In zsh, if there's either no day or night file, the last two commands will fail; set the nonomatch or csh_null_glob option, or add (N) after each pattern to avoid this.

2
  • 1
    What about *{day,night}*. I'd edit it, but I don't know which shells support it?
    – Random832
    Oct 8, 2012 at 15:12
  • @Random832 Works in bash, ksh, and zsh (none need extended globbing), but not sh - however, Nahuel's last "all shells" example does work in sh.
    – Izkata
    Oct 8, 2012 at 18:04
15

Shells do not uses regular expressions for argument expansion.

You can enable the extended pattern matching by

$ shopt -s extglob

and then

$ ls @(day|night).txt
day.txt   night.txt

See for example the Bash Reference Manual (Pattern Matching)

0
-2

You can pipe ls with grep as below

aashutosh@ubuntu:/tmp$ ls -ltrh
total 0
-rw-rw-r-- 1 aashutsh user 0 May  9 02:55 noon.txt
-rw-rw-r-- 1 aashutsh user 0 May  9 02:55 night.txt
-rw-rw-r-- 1 aashutsh user 0 May  9 02:55 day.txt

aashutosh@ubuntu:/tmp$ ls -ltr | grep 'night\|day'
-rw-rw-r-- 1 aashutsh user 0 May  9 02:55 night.txt
-rw-rw-r-- 1 aashutsh user 0 May  9 02:55 day.txt
1
  • Unfortunately, that would also pick up on file entries where e.g. the owning user or group contains day or night, not only the filename.
    – AdminBee
    May 9 at 8:19

Not the answer you're looking for? Browse other questions tagged or ask your own question.