94

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

117

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

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

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? Commented Oct 8, 2012 at 15:12
  • 1
    @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. Commented Oct 8, 2012 at 18:04
17

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. Commented May 9, 2022 at 8:19

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.