Check type of executable file
if(argc &lt; 2){
    printf(&quot;The path to the file is\n&quot;);
    return 1;
}


The error message is unfinished (appropriately enough, missing is missing), and it should go to stderr, not stdout.

if(stat(argv[1],&amp;fileStat) &lt; 0){
    printf(&quot;error\n&quot;);
    return 1;
}


Again we're writing to the wrong stream.  And we could make a more informative message, e.g. perror(argv[1]).

        Search_in_File(argv[1], &quot;#!&quot;);
        Search_in_File(argv[1], &quot;ELF&quot;);


These two calls each open the file to read it.  It is probably better to open the file just once.  Why do we ignore the return value each time?

while(fgets(temp, 512, fp) != NULL) {
    if((strstr(temp, str)) != NULL) {
        ⋮
    }
}


This code will fail to match when the search string straddles a 512-byte boundary.  But why are we searching the whole file anyway?  Those magic strings are only meaningful as the first characters, and do not tell us anything if they occur later in the file.  We could do this much more simply:
if (fread(temp, 4, 1, fp) == 1
    &amp;&amp; strncmp(temp, str, strlen(str)) == 0) {
    ⋮
}


        if(strcmp(str, &quot;#!&quot;)==0)
            printf(&quot;shell type.&quot;);
        else if(strcmp(str, &quot;ELF&quot;)==0)
            printf(&quot; ELF.&quot;);


Instead of string-matching the str argument, why not just pass an additional argument specifying the string to print?  Then there's only one place to modify when you add a new test.

if(fp) {
    fclose(fp);
}


At this point, we know that fp is non-null, since we already returned if it isn't.
Oh, and an executable that begins with #! could be any type of interpreted executable (e.g. Python or Sed script), not necessarily a shell script.  Not sure whether that's what's intended (is it your description or the program that needs adjusting?).