1. Overview
Using pattern matching, we sometimes use the logical OR operator to locate items that match one of two or even more conditions. For example, this is the case when we want to list files that have either two extensions or if they contain certain characters or strings.
The standard shell globbing can help us create a great deal of pattern-matching expressions. However, every now and then we may need to use more advanced globbing rules or leverage other shell features at our disposal.
In this tutorial, we’ll dive into the various ways of applying the logical OR with shell globs.
2. Using the Alternation Wildcard |
The pipe symbol is one of the common symbols to denote the OR operator in regular expressions and programming languages. However, this wildcard isn’t recognized by default in the standard globular expressions.
2.1. Extended Pattern Matching
To use the OR operator in shell globs matching, we must kickstart by enabling the shell extended globs.
Let’s expand the wildcard options with the shopt command:
$ shopt -s extglob
This command uses the -s flag (short for set) to enable the extglob option which lets our shell understand several other extended pattern-matching operators. An important thing to note is that the shopt command only affects the current shell session.
2.2. Applying the Logical OR Operator
Now, we can use the | alternation operator, let’s say, to list files that contain either alpha or sigma:
$ ls -l *@(alpha|sigma)*
-rw-r--r-- 1 ZZZ 33011 0 Aug 5 12:37 7_sigma_bouhannana
-rw-r--r-- 1 ZZZ 33011 0 Aug 5 12:37 alpha_51
-rw-r--r-- 1 ZZZ 33011 0 Aug 5 12:37 sigma_33
The ls command above captured all matching files, thanks to the @() construct that compares against each of the supplied strings.
Since extglob is enabled, we can supply our patterns within @(). Of course, we should separate the specified patterns with the pipe symbol to apply the logical OR formula. Moreover, we put the asterisk * before and after the @() construct to match any surrounding character zero or more times. In other words, the * wildcards matched the 7_ and _bouhannana in the 7_sigma_bouhannana filename.
3. Using Brace Expansion
We can use the brace expansion mechanism to get the same results as before without the hassle of extending the shell globs.
Using the last command, let’s keep the basic globbing asterisk wildcards as they are and switch what’s in between to a brace expression:
$ ls *{alpha,sigma}*
-rw-r--r-- 1 ZZZ 33011 0 Aug 5 12:37 7_sigma_bouhannana
-rw-r--r-- 1 ZZZ 33011 0 Aug 5 12:37 alpha_51
-rw-r--r-- 1 ZZZ 33011 0 Aug 5 12:37 sigma_33
The curly brace expression expands to the given comma-separated values which results in something similar to *alpha* and *sigma*. Then, the ls command takes care of the rest and matches the expanded results against our filenames.
4. Using Linux Commands
Understanding how the commands we use work, may spare us the hassle of using any of the previous examples.
For instance, let’s check the ls command syntax, ls [options] [files] — we can notice that it takes one or more files as an argument. Thus, the OR operator is automatically in effect when we feed multiple file arguments into ls.
Let’s give this a go without explicitly applying the OR operator:
$ ls -l *sigma* *alpha*
-rw-r--r-- 1 ZZZ 33011 0 Aug 5 12:37 7_sigma_bouhannana
-rw-r--r-- 1 ZZZ 33011 0 Aug 5 12:37 alpha_51
-rw-r--r-- 1 ZZZ 33011 0 Aug 5 12:37 sigma_33
Our ls command here, natively understands that it should only match two file arguments (patterns) against the filenames. This method sure spares us the hassle of using other or extended Linux features. However, it isn’t cleaner compared to our previous examples, especially if we want to match a long list of patterns.
5. Using the Character Class
We can also use the OR operator in shell globbing to match single characters instead of strings. By using square brackets, also called a character class, we can define a set or a range of characters to match filenames that contain any of the defined characters.
Let’s list all files that start with either 7 or s:
$ ls -l [7s]*
-rw-r--r-- 1 ZZZ 33011 0 Aug 5 12:37 7_sigma_bouhannana
-rw-r--r-- 1 ZZZ 33011 0 Aug 5 12:37 sigma_33
Our pattern starts with the [7s] set instead of a wildcard, which means the command considers only filenames that begin with the digit 7 or the lowercase letter s.
Now, let’s specify a range of characters and list any filename with a digit or an uppercase character:
$ ls -l *[A-Z0-9]*
-rw-r--r-- 1 ZZZ 33011 0 Aug 5 12:37 7_sigma_bouhannana
-rw-r--r-- 1 ZZZ 33011 0 Aug 11 14:41 Bee.log
-rw-r--r-- 1 ZZZ 33011 0 Aug 5 12:37 alpha_51
-rw-r--r-- 1 ZZZ 33011 0 Aug 5 12:37 sigma_33
In the character class above, we’re performing a logical OR to get a match from two specific ranges:
- A-Z matches any uppercase letter from A to Z
- 0-9 matches any digit between 0 and 9
We can add any character or range we need accordingly.
6. Conclusion
In this article, we talked about using the logical OR operator through extended globbing, brace expansion, the ls command, and character classes.
In conclusion, we can apply the logical OR using different formats and methods. However, when dealing with complex logical conditions, it’s usually best to opt for the cleanest approach to get the desired results without unnecessary hassle.