4

My directory looks like this:

$ ls
total 0
-rw-r--r-- 1 user user 0 Jun 18 22:44 file0
-rw-r--r-- 1 user user 0 Jun 18 22:44 file1
-rw-r--r-- 1 user user 0 Jun 18 22:44 file2
-rw-r--r-- 1 user user 0 Jun 18 22:44 file3
-rw-r--r-- 1 user user 0 Jun 18 22:44 file4
-rw-r--r-- 1 user user 0 Jun 18 22:44 file5
-rw-r--r-- 1 user user 0 Jun 18 22:44 file6
-rw-r--r-- 1 user user 0 Jun 18 22:44 file7
-rw-r--r-- 1 user user 0 Jun 18 22:44 file8
-rw-r--r-- 1 user user 0 Jun 18 22:44 file9

Using bash globbing, I want to match file2 to file6, excluding file3.

Since I could not find an and operator for matching multiple patterns, I figured I just use DeMorgan's law that a AND b is equivalent to !(!a OR !b) and write

!(!(file[2-6])|file3)

which works as expected:

$ echo !(!(file[2-6])|file3)
file2 file4 file5 file6

Is there an easier, more direct way to achieve this?

3
  • 1
    Does the real life issue on your system also include removing a single name from a set of matching names in a short numerical range, like in your question, or is the actual situation more complex?
    – Kusalananda
    Jun 19 at 11:28
  • 1
    @Kusalananda I am looking for a solution that works for the abstract problem of matching everything that matches pattern1 but not pattern2. Jun 19 at 14:37
  • 1
    That makes your example rather deceptive as it's easy to leave out 4 from file[23456]. You may want to update your question with a further explanation of the general issue so that people here don't think you're interested in the specific example you are showing (which is now the case).
    – Kusalananda
    Jun 19 at 14:44

2 Answers 2

4

You can apply two ranges [24-6], where 2 is the first and 4-6 is the second:

$ ls file[24-6]
file2 file4 file5 file6

Another example:

$ ls file[2356]
file2 file3 file5 file6

Documentation:

Ranges

There is one special convention: two characters separated by '-' denote a range. (Thus, "[A-Fa-f0-9]" is equivalent to "[ABCDEFabcdef0123456789]".) One may include '-' in its literal meaning by making it the first or last character between the brackets. (Thus, "[]-]" matches just the two characters ']' and '-', and "[--0]" matches the three characters '-', '.', '0', since '/' cannot be matched.)

0
2

negate range :

printf '%s\n' file[!013789]

As stated here :

If the first character following the ‘[’ is a ‘!’ or a ‘^’ then any character not enclosed is matched.


setting GLOBIGNORE to the file you want to skip:

GLOBIGNORE="file0:file1:file3:file7:file8:file9"
printf '%s\n' file*

see this :

The GLOBIGNORE shell variable may be used to restrict the set of file names matching a pattern. If GLOBIGNORE is set, each matching file name that also matches one of the patterns in GLOBIGNORE is removed from the list of matches.


Using extended globbing:

shopt -s extglob
printf '%s\n' file!([013789])

see extended globbing

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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