Merge all files in a directory with a specific extension I come from Python, with a bit a FORTRAN and Matlab some years ago. 
I'm trying to learn C. My first attempt at a program is one to merge all the files in a directory with a specified extension

/*
MERGE: Merges text files. Gives the ability to all files in a 
directory with specified extension.
*/
#include &lt;stdio.h&gt;
#include &lt;dirent.h&gt;
#include &lt;stdbool.h&gt;
#include &lt;string.h&gt;
#include &lt;stdlib.h&gt;

/* Function prototypes */
int append_to_file(const char *filename, const char *outfilename); // Appends the contents of filename to outfilename
int scandir(char dirname[], char const *ext, char outfile[]); // Scans a directory for files of a specific extension and merges them
bool has_extension(char const *name, char const *ext);
void usage(); // Prints out usage information (help) to the console
void path_combine(char *dest, const char *path1, const char *path2); // Combines a directory name and filename to a single filepath

int main(int argc, char *argv[])
{    
    int nfiles; // Number of files merged

    if (argc == 4)
    {
        nfiles = scandir(argv[1], argv[2], argv[3]);      
        printf("Merged %d files\n", nfiles);

        return 0;  
    }
    else
    {
        printf("Wrong input, quitting");
        return 1;
    }

}

int append_to_file(const char *filename, const char *outfilename)
{
    FILE *infile, *outfile;
    char ch;
    infile = fopen(filename, "r");
    outfile = fopen(outfilename, "a");

    if (infile == NULL)
    {
        printf("Input file is empty, skipping...\n");
        return 1;
    }

    while ((ch = fgetc(infile)) != EOF)
        fputc(ch, outfile);

    printf("Appended file\n");

    fclose(infile);
    fclose(outfile);

    return 0;

}

int scandir(char dirname[], char const *ext, char outfile[])
/* Scans a directory and merges all files of given extension */
{
    DIR *d = NULL;
    struct dirent *dir = NULL;
    char filepath[strlen(dirname) + 255];
    int i = 0;   

    d = opendir(dirname);

    if (d)
    {
        while ((dir = readdir(d)) != NULL)
        {   
            if (has_extension(dir-&gt;d_name, ext))
            {   

                path_combine(filepath, dirname, dir-&gt;d_name);
                printf("%s\n", filepath);
                append_to_file(filepath, outfile);
                i++;
            }

        }
        closedir(d);
    }
    return i;
}


bool has_extension(char const *name, char const *ext)
{
    size_t len = strlen(name);
    return len &gt; 4 &amp;&amp; strcmp(name+len-4, ext) == 0;
}


void path_combine(char *dest, const char *path1, const char *path2)
{
    const char *last_char = path1;
    int append_sep = 0;
    char sep[] = "/";

#ifdef WIN32
    sep[0] = '\\';
#endif

    /* Find the last character in the first path*/
    while(*last_char != '\0')
        last_char++;

    /* If the last character is not a seperator, we must add it*/
    if (strcmp(last_char, sep) !=0)
    {
        append_sep = 1;
    }

    strcpy(dest, path1);
    if (append_sep)
        strcat(dest, sep);
    strcat(dest, path2);       

}


void usage()
{
    printf("\t=================\n");
    printf("\t      MERGE\n");
    printf("\t=================\n");
    printf("Merge two or more text files\n");
    printf("Usage:\n");
    printf("\tCall merge with a directory name and desired extension:\n");
    printf("\tmerge DIRNAME .csv OUTPUTFILE\n\n");

};


I realise there are many things I haven't done here (such as any real error handling), but bear in mind this is a first attempt as part of the learning process. 
Rather than being told to 'go look up xx' where xx is a whole area of learning, I'm more interested in specifics if possible. 

Are there any obvious code smells? 
Is there anything that could obviously be implemented better?
Particularly usage of pointers, which I am still getting to grips with.
scandir

It is not a good name for 2 reasons. First, it exists in a global namespace, and second, it doesn't tell what the function does. Your scandir not only scans the directory, but does an actual merge as well. I would recommend to scan the directory with a standard library's scandir and then merge files (from the list it returns) in a merge function.

A perk benefit of using a stock scandir is an ability to control the merge order. Right now it is unpredictable.

Yet another benefit of separating responsibilities is that if outfile is in the same directory with source files and it has an target extension, the results could be very strange.
has_extension presumes that the extension is always 3 characters. It is not necessarily so. It should calculate an actual length of the ext argument.
append_to_file produces a misleading diagnostics. The fopen may fail for many reasons, but file being empty is not one of them. Display the error message with perror or strerror.
path_combine

Contrary to a popular belief, windows understands a forward slash as a path separator (backslash is an artifact of cmd.exe). There's no need to special case windows.

It is also not necessary to test for last character for being a separator. Just add the separator anyway, it is harmless.

That said, I don't think that you need it at all: just chdir() to the source directory first.