What Happens When You Type ls *.c

In the most simple way possible the command ls *.c lists all the files in the current directory that end with “.c”. But what exactly is going on in the shell to get us there?
The first thing the shell does is check the input given to it for different words. So, with the command ls *.c, the shell recognizes two separate words here since ls and *.c are separated by spaces. Now that it has the two words it looks at the first to see if it’s an alias for another command. If there is an alias set up the shell looks at the new command and sees if it’s an alias, and will keep doing this until it finds a command that is not aliased to anything else. So, if ls had an alias setup for rm, but rm didn’t have any aliases then the shell would replace the ls with rm in the command. Thus making:
ls *.c
into:
rm *.c
Which is a drastically different command. Once, the shell has found the appropriate command, the non-aliased one, it will then look to the second word it sees. In this case “*.c”, and see if there is any expansions to run. In this case we have the ‘*’ character, which is an expansion. The ‘*’ expansion looks for all files ending with what follows it, in this case “.c”. If the the “.c” had happened before the ‘*’ then it would look for all files that started with “.c”. It would this expand this out to list all those files in the command line. So, assuming are ls wasn’t aliased this would look something like this:
ls foo.c boo.c
After that the shell would then run the command with all the arguments given. So in this situation it would list the names of all the files in the directory matching those names it previously put in the command line. Once it runs the command it exits and then the shell prints the command prompt based off of what is set in the PS1 variable.
Then that’s that. The shell has properly ran the command given to it, and the user can now give the shell any other command they need to.