6

In my directory, I have a list of files with different extensions such as

file-abc-12.out
file-abc-12.csv
file-abc-12.txt
file-xyz-12.out
file-xyz-12.csv
file-xyz-12.txt
file-abc-04.out
file-abc-04.csv
file-abc-04.txt
file-xyz-04.out
file-xyz-04.csv
file-xyz-04.txt

If I only want to list the files that contain abc and end in a .out, how would I do that. I want to perform a ls or a find using two pattern matching searches *abc* and *out. I only know how to search one or the other at a time, how would I have it search for file names with both conditions?

6
  • 3
    ls *abc*.out? Commented Apr 14, 2017 at 17:35
  • @DopeGhoti should be printf '%s\n' *abc*.out Commented Apr 14, 2017 at 17:51
  • 1
    From the OP: "I want to perform a ls or find". Commented Apr 14, 2017 at 17:52
  • 1
    The trick is in realising that there is no such thing as a file extension: the dot in the file-name is not special. The idea of filename extensions comes from Microsoft's windows/dos versions <= 3.1 and cp/m. Commented Apr 14, 2017 at 22:46
  • 1
    @cuonglm there's no reason to use printf here, why? The OP hasn't suggested they want to parse the output, only list the names. Why would printf be useful here? Commented Apr 15, 2017 at 0:31

3 Answers 3

10

This will give you what you want:

$ find . -name '*abc*' -o -name '*out'
2
  • 2
    Thank you for responding first and foremost. The command you gave seems to list all the files that have 'abc' contained in the file name OR end with '.out'. I want a command that will list all the files that contain 'abc' AND end with '.out' Commented Apr 14, 2017 at 23:44
  • Odd, this doesn't work for me. It's not giving me any results. Commented Jan 13, 2020 at 21:03
4

I'm interpreting the "and" used in the question as a strict "logical and", i.e. as "find files whose names match both *abc* and *out".

You may use multiple wildcards in one filename globbing pattern:

$ ls *abc*out

or

$ find . -type f -name "*abc*out"

for example.

The pattern *abc*out would match any name containing the string abc and then ending in out.

If no file matches the pattern, the pattern will be left unexpanded. If that happens, ls will get the pattern *abc*out as the argument rather than a valid filename, and will complain about ls: cannot access *abc*out: No such file or directory.

To make bash display an error about not being able to expand a file globbing pattern rather than passing the unexpanded pattern to ls, set the failglob shell option:

bash-4.4$ ls *abc*out
ls: *abc*out: No such file or directory

bash-4.4$ shopt -s failglob

bash-4.4$ ls *abc*out
bash: no match: *abc*out
2
  • Hmm my shell doesn't seem to accept that. I get the following message: ls: cannot access *abc*out: No such file or directory Commented Apr 14, 2017 at 23:40
  • @TySeyoum This is because you don't actually have any file matching that pattern. Since no file matches the pattern, the pattern is left unexpanded, ls tries to use it as a filename, but fails. Commented Apr 15, 2017 at 6:20
-3

The solution I found to work for me involved using grep. It follows:

$ ls *out | grep "abc"

2
  • 2
    Please don't use this! It will break on strange file names and all you need is ls *abc*out. If what you show works, then so does ls *abc*out. The error you menition under Kusalananda's answer suggests you might have run ls '*abc*out' instead. For more on why this is a bad approach, see here. Commented Apr 15, 2017 at 0:28
  • @terdon You're exactly right. I tried it again and it worked. Thank you! Commented Apr 18, 2017 at 18:47

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.