21

I want to list all files in a directory that start with 'abc' and end with '.zip'

I'm trying to use ls.

The directory has a lot of zip files starting with abc<date> and xvz<date>. I only want to get the list of the abc<date>.zip

1
  • 1
    ls -1 | grep "abc$(your_date).zip" ? Commented Jan 16, 2018 at 19:54

5 Answers 5

26

ls doesn't do pattern matching on file names¹. It just lists the content of the directories and the files it is being given as arguments.

Your shell on the other hand has a feature called globbing or filename generation or pathname expansion that expands a pattern into a list of files matching that pattern.

Here that glob pattern would be abc*.zip (* being a wildcard that stands for any number of characters).

You'd pass it to any command you like such as printf for printing:

printf '%s\n' abc*.zip 

You could also pass it to ls -l to display the attributes of those files:

ls -ld abc*.zip 

(we need -d because if any of those files are of type directory, ls would list their content otherwise).

Or to unzip to extract them if only unzip could extract more than one file at a time. Unfortunately it doesn't, so you'd need either to use xargs -n1 or a for loop:

printf '%s\0' abc*.zip | xargs -r0n1 unzip 

Or:

for file in abc*.zip; do unzip "$file"; done 

But in fact, unzip being more like a port of a MS-DOS command, unzip itself would treat its argument as a glob. In other words, unzip 'abc*.zip' will not unzip the file called abc*.zip (a perfectly valid file name on Unix, not on Microsoft operating systems), but the files matching the abc*.zip pattern, so you'd actually want:

 unzip 'abc*.zip' 

(Actually our xargs and for approach above would be wrong, because if there's a file called abc*.zip for instance, unzip would treat it as a pattern! See bsdtar for a more unixy way to extract zip archives)


For case insensitive matching, you'd use [aA][bB][cC]*.[zZ][iI][pP]² portably. Some shells have extended globbing operators for case insensitive matching:

  • zsh:

    setopt extendedglob ls -ld (#i)abc*.zip 

    Or:

    ls -ld ((#i)abc)*.zip 

    if you only want the abc part to be case insensitive.

  • ksh93:

    ls -ld ~(i)abc*.zip 

    or:

    ls -ld ~(i:abc)*.zip 
  • with bash.

    shopt -s nocaseglob ls -ld abc*.zip 

    (no way to have only parts of the globs case sensitive there other than by using the portable syntax).

  • with yash:

    set +o case-glob ls -ld abc*.zip 

    same remark as for bash above.


¹ Unless you want to consider the -I PATTERN/--ignore=PATTERN/--hide=PATTERN non-standard extensions of the GNU implementation of ls.

² Though note that in several shells including bash, if the pattern doesn't match any file, it is passed as-is to the command, which could then end up extract a file called [aA][bB][cC]*.[zZ][iI][pP] literally. Setting the failglob option in bash avoids the problem.

2
  • In bash ls -ld l*.so gives me ls: cannot access 'l*.so': No such file or directory. Am I missing something? Commented Jun 8, 2022 at 17:24
  • @OfekShilon, you'd need to run that from within a directory that has at least one entry whose name starts with l and ends in .so (and the noglob option of your shell, assuming it's POSIX-like not to be enabled). Commented Jun 8, 2022 at 17:58
17
ls abc*.zip 

This however will fail if there are too many files (there is a limit to shell expansion in term of how many arguments it can expand to).

find . -name "abc*.zip" 

This is probably the most universal. The quotes must be there. With some find implementations, you can also use -iname instead of -name for case insensitive search (aBc<date>.ZIP would also match).

ls | grep -x "abc.*\.zip" 

Mind the .* and \. since the filter grep uses is regex which is different from the wildcard notation the shell uses for expansion. Use grep -i for case insensitive search.

3
  • 1
    Note that that limit is not a shell limit. It's a kernel limit in the execve() system call. Commented Apr 19, 2016 at 13:25
  • It should probably be noted that find will look for those files in subdirectories as well. Use find . ! -name . -prune -name 'abc*.zip' -print or find . -maxdepth 1 -name 'abc*.zip' if your find supports -maxdepth like on GNU or BSD or find . -depth 1 -name 'abc*.zip' if your find supports a -depth <n> like on some BSDs to restrict to the current directory. Commented Apr 19, 2016 at 13:28
  • $ ls ../*.a worked for me (list archives in parent dir). Commented Jan 24, 2018 at 16:38
1

You can pipe the output of ls to grep.

Let's say I want to find all files that contain abc in the filename

ls -f | grep abc 

If you need specific variations of patterns, man grep

1
0

Try using ls abc*.zip to narrow down the results to those matching your criteria for a starting string of abc and an ending of .zip The asterisk will expand to match those results without including xvz starting characters.

-1

You must specified the directory where ls will search in an example

ls -la ~/file*.* ls -la ./file*.* 

it works for me, but obviously it doesn't support searching by pattern

1
  • 1
    This doesn't address the question; the files should start with abc and end with .zip. Commented Sep 8, 2018 at 0:38

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.