Skip to content

Instantly share code, notes, and snippets.

@morganabc
Created March 27, 2025 04:13
Show Gist options
  • Select an option

  • Save morganabc/b225b0d2754caa4fc479c0fab9f9e6d7 to your computer and use it in GitHub Desktop.

Select an option

Save morganabc/b225b0d2754caa4fc479c0fab9f9e6d7 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
long count = 0;
int path_exists(const char *path) {
struct stat st;
return stat(path, &st) == 0;
}
void find_missing(const char *old_base, const char *new_base, const char *relative_path) {
char old_path[4096];
char new_path[4096];
if (relative_path[0] == '\0') {
snprintf(old_path, sizeof(old_path), "%s", old_base);
snprintf(new_path, sizeof(new_path), "%s", new_base);
} else {
snprintf(old_path, sizeof(old_path), "%s/%s", old_base, relative_path);
snprintf(new_path, sizeof(new_path), "%s/%s", new_base, relative_path);
}
if (!path_exists(new_path)) {
printf("Missing: %s\n", relative_path[0] == '\0' ? old_base : old_path);
return;
}
DIR *dir = opendir(old_path);
if (!dir) {
perror("opendir");
return;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
count++;
if (count % 100000 == 0) {
fprintf(stderr, "%ld\r", count);
}
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
char next_relative_path[4096];
char next_old_path[4096];
if (relative_path[0] == '\0') {
snprintf(next_relative_path, sizeof(next_relative_path), "%s", entry->d_name);
} else {
snprintf(next_relative_path, sizeof(next_relative_path), "%s/%s", relative_path, entry->d_name);
}
snprintf(next_old_path, sizeof(next_old_path), "%s/%s", old_path, entry->d_name);
struct stat st;
if (lstat(next_old_path, &st) != 0) {
fprintf(stderr, "Error stating %s\n", next_old_path);
continue;
}
if (S_ISDIR(st.st_mode)) {
if (!S_ISLNK(st.st_mode)) {
find_missing(old_base, new_base, next_relative_path);
}
} else {
char next_new_path[4096];
snprintf(next_new_path, sizeof(next_new_path), "%s/%s", new_path, entry->d_name);
if (!path_exists(next_new_path)) {
printf("Missing: %s\n", next_new_path);
}
}
}
closedir(dir);
}
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s [OLD_PATH] [NEW_PATH]\n", argv[0]);
return 1;
}
const char *old_path = argv[1];
const char *new_path = argv[2];
if (!path_exists(old_path)) {
fprintf(stderr, "Error: '%s' does not exist\n", old_path);
return 1;
}
if (!path_exists(new_path)) {
fprintf(stderr, "Error: '%s' does not exist\n", new_path);
return 1;
}
find_missing(old_path, new_path, "");
fprintf(stderr, "Total: %ld\n", count);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment