Search for *.swo

I think this should be an easy one, but it's got me stumped.

When I use the following, it finds the file.

$ ls -al  .bash_*.sw*   
-rw-r--r--  1 damiensawyer  staff  12288 27 Nov 07:39 .bash_profile.swo

But when I use this, it doesn't find it.

$ ls -al *.sw*      
ls: *.sw*: No such file or directory

I expected the second command to also return .bash_profile.swo. What am I missing?


Solution 1:

Using ls

The problem is that your file has two dots, not one. You need to account for that:

ls -al .*.sw*

This will match any file that begins with a dot (invisible files like .DS_Store) and also ends with .sw*.

.swa as well as .swz will match.


Using find

You can use the following to find all files with the same extension (swo in the case below) in a directory.

find ~ -iname *swo

-iname finds a case insensitive match.


You can search for that/those specific file(s) using this:

find .bash_*.sw*

Note: Using ~ as the path will search your entire home directory.

Solution 2:

This is not actually caused by ls, since ls never expands patterns.

The decision about how to expand glob patterns (patterns containing * and ?) is made by the shell. Your shell is most likely bash.

By default bash does not perform path expansion on dotfiles. However, it can do so either by explicitly writing the . (as you discovered already) or by turning on the dotglob option. From the bash manpage:

dotglob If set, bash includes filenames beginning with a `.' in the results of pathname expansion.

To demonstrate, let's just print the expansion with echo instead of ls:

$ touch .bash_profile.swo

$ echo .*.swo
.bash_profile.swo

$ echo *.swo
*.swo

$ shopt -s dotglob

$ echo *.swo
.bash_profile.swo

Futher discussion can be found here.

Solution 3:

The issue is that ls only shows files that begin with a . you have to explicitly have the first . in the file glob.

Thus the following will work:

ls .*swo

Unix shells expand the glob before ls sees the file names.

Solution 4:

These patterns (*.sw* and the like) are known as globs.

As @Mark and @Zach Gates have noted, globs do not match files whose names begin with a period unless you explicitly include a . at the beginning of the pattern. This is because in UNIX-like systems (such as OS X), files that begin with a dot are considered 'hidden' files and are generally not shown by default.

Glob matching is actually done by your shell (bash by default), not by individual commands such as ls. As the bash manual explains under Filename Expansion:

After word splitting... Bash scans each word for the characters ‘*’, ‘?’, and ‘[’. If one of these characters appears, then the word is regarded as a pattern, and replaced with an alphabetically sorted list of filenames matching the pattern (see Pattern Matching). If no matching filenames are found,...the word is left unchanged.

When a pattern is used for filename expansion, the character ‘.’ at the start of a filename or immediately following a slash must be matched explicitly, unless the shell option dotglob is set.