{"id":377492,"date":"2026-09-28T16:49:10","date_gmt":"2026-09-28T16:49:10","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/fruti-media-integrity-audit\/"},"modified":"2026-10-08T12:34:03","modified_gmt":"2026-10-08T12:34:03","slug":"fruti-media-integrity-audit","status":"publish","type":"plugin","link":"https:\/\/bal.wordpress.org\/plugins\/fruti-media-integrity-audit\/","author":23575675,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0.1","stable_tag":"1.0.1","tested":"7.1.3","requires":"6.0","requires_php":"8.1","requires_plugins":null,"header_name":"Fruti Media Integrity Audit","header_author":"Fruti Labs","header_description":"Read-only report of Media Library files missing from disk and uploads files that no attachment claims. Never deletes, moves, imports or repairs anything.","assets_banners_color":"0d282f","last_updated":"2026-10-08 12:34:03","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"","rating":0,"author_block_rating":0,"active_installs":0,"downloads":126,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.0":{"tag":"1.0.0","author":"frutilabs","date":"2026-09-28 16:41:34","revision":3717601},"1.0.1":{"tag":"1.0.1","author":"frutilabs","date":"2026-10-08 12:34:03","revision":3734575}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3717601,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3717601,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3717601,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3717601,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.0","1.0.1"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3717601,"resolution":"1","location":"assets","locale":"","width":1440,"height":1100},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3717601,"resolution":"2","location":"assets","locale":"","width":1440,"height":900}},"screenshots":{"1":"After a migration: how many files WordPress expects are missing, how many uploads files nothing claims, and how many could not be classified - for the window you scanned.","2":"The exact list: file, attachment ID, title and an Edit link for every missing file - so you restore the right ones and delete nothing blindly."}},"plugin_section":[],"plugin_tags":[23519,84,4155,205290,152],"plugin_category":[50,59],"plugin_contributors":[283185],"plugin_business_model":[],"class_list":["post-377492","plugin","type-plugin","status-publish","hentry","plugin_tags-diagnostics","plugin_tags-media","plugin_tags-migration","plugin_tags-missing-images","plugin_tags-restore","plugin_category-media","plugin_category-utilities-and-tools","plugin_contributors-frutilabs","plugin_committers-frutilabs"],"banners":{"banner":"https:\/\/ps.w.org\/fruti-media-integrity-audit\/assets\/banner-772x250.png?rev=3717601","banner_2x":"https:\/\/ps.w.org\/fruti-media-integrity-audit\/assets\/banner-1544x500.png?rev=3717601","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/fruti-media-integrity-audit\/assets\/icon-128x128.png?rev=3717601","icon_2x":"https:\/\/ps.w.org\/fruti-media-integrity-audit\/assets\/icon-256x256.png?rev=3717601","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/fruti-media-integrity-audit\/assets\/screenshot-1.png?rev=3717601","caption":"After a migration: how many files WordPress expects are missing, how many uploads files nothing claims, and how many could not be classified - for the window you scanned."},{"src":"https:\/\/ps.w.org\/fruti-media-integrity-audit\/assets\/screenshot-2.png?rev=3717601","caption":"The exact list: file, attachment ID, title and an Edit link for every missing file - so you restore the right ones and delete nothing blindly."}],"raw_content":"<!--section=description-->\n<p>You moved, restored or copied your site, and some images no longer appear. Before you delete, re-import,\nregenerate or clean anything, find out what is actually missing.<\/p>\n\n<p>Fruti Media Integrity Audit compares your Media Library with the files that exist in your uploads directory and\nreports two things:<\/p>\n\n<ul>\n<li><strong>Missing files<\/strong> - attachments, including the image sizes recorded in their metadata, that WordPress expects\nto exist but that are absent from the local filesystem. This is not a guess: WordPress itself says the file\nshould be there.<\/li>\n<li><strong>Orphan candidates<\/strong> - files present in the uploads tree that no attachment metadata claims.<\/li>\n<\/ul>\n\n<p>It also counts <strong>derived<\/strong> files (the resized and alternate copies that come from your registered image sizes).\nThey are counted, not listed, because they follow their original.<\/p>\n\n<p>It is a diagnostic. It never deletes, moves, renames, imports, regenerates or repairs anything, it does not\nmodify attachment metadata, and it writes nothing to your database.<\/p>\n\n<p>The plugin is deliberately conservative. A file is only reported as an orphan candidate when its own directory\nis already referenced by an attachment from the current scan window. Everything else is listed as\n<em>unknown \/ not classified<\/em> instead of being called orphaned, because a wrong \"orphan\" label is worse than no label.<\/p>\n\n<p>Useful after a migration, a backup restore, a host move or an offload\/CDN change, and as a sanity check before\nrunning any cleanup tool.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin folder to <code>\/wp-content\/plugins\/<\/code>, or install the ZIP through\nPlugins -&gt; Add New -&gt; Upload Plugin.<\/li>\n<li>Activate the plugin.<\/li>\n<li>Go to Tools -&gt; Fruti Media Integrity Audit and press \"Run audit\".<\/li>\n<\/ol>\n\n<h4>How to use it<\/h4>\n\n<ol>\n<li>Open Tools -&gt; Fruti Media Integrity Audit.<\/li>\n<li>Press <strong>Run audit<\/strong>. The plugin checks the attachment window and scans the uploads window you configure under\n\"Advanced: scan window\" (the defaults are safe for most sites).<\/li>\n<li>Read the two result groups. Missing files are checked exactly: WordPress metadata says the file should exist\nand it does not.<\/li>\n<li>If the notice says the file scan hit its per-run limit, the window is partial - raise the file offset and run\nagain to inspect the rest.<\/li>\n<li>Press <strong>Download CSV for this window<\/strong> to export the current results. The CSV is generated on the fly and is\nnever stored.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"i%20migrated%20or%20restored%20my%20site%20and%20images%20are%20missing.%20what%20should%20i%20do%3F\"><h3>I migrated or restored my site and images are missing. What should I do?<\/h3><\/dt>\n<dd><ol>\n<li>Run the audit and read the <strong>Missing files<\/strong> list. Those are the files WordPress expects at exact paths - they\nare what makes images (and their thumbnails) disappear.<\/li>\n<li>Look for the same relative paths in a recent backup, on the old host or in your hosting file manager, and copy\nthe files back to those same paths. Do not delete the attachments: their metadata is still correct, so\nrestoring the file is usually enough.<\/li>\n<li>Treat <strong>Orphan candidates<\/strong> as candidates only. Check a few in the Media Library before removing anything, and\ntake a backup first.<\/li>\n<li>Leave <strong>Unknown \/ not classified<\/strong> alone. Those files are outside this scan window or cannot be attributed\nsafely.<\/li>\n<li>Nothing needs to be \"repaired\" by this plugin: it reports, and you decide with the tool of your choice.<\/li>\n<\/ol><\/dd>\n<dt id=\"what%20to%20do%20after%20the%20report%3F\"><h3>What to do after the report?<\/h3><\/dt>\n<dd><p>The report is a diagnosis; nothing on your site has been changed. Take a full backup before any repair or\ncleanup, restore genuinely missing files from a backup where you can, verify candidates by hand before deleting,\nand leave unclassified files untouched. If a migration tool moved your files, fix the files or their paths, not\nthe attachments.<\/p><\/dd>\n<dt id=\"does%20this%20plugin%20delete%20or%20fix%20anything%3F\"><h3>Does this plugin delete or fix anything?<\/h3><\/dt>\n<dd><p>No. It is strictly read-only: no deletion, no import, no thumbnail regeneration, no metadata change, no automatic\nrepair. Fixing is a decision you make with another tool, after reading this report.<\/p><\/dd>\n<dt id=\"can%20it%20see%20files%20outside%20my%20uploads%20directory%3F\"><h3>Can it see files outside my uploads directory?<\/h3><\/dt>\n<dd><p>No. It only inspects the uploads tree that WordPress itself reports, it never accepts a path from the browser, and\nsymlinks are not traversed.<\/p><\/dd>\n<dt id=\"why%20are%20some%20files%20listed%20as%20%22unknown%22%20instead%20of%20orphaned%3F\"><h3>Why are some files listed as \"unknown\" instead of orphaned?<\/h3><\/dt>\n<dd><p>Because the plugin refuses to guess. If a file's directory is not referenced by any attachment in the current\nwindow, the plugin cannot tell whether the file is unused or simply belongs to a part of the library outside this\nwindow, so it reports it as unknown.<\/p><\/dd>\n<dt id=\"what%20happens%20on%20very%20large%20media%20libraries%3F\"><h3>What happens on very large media libraries?<\/h3><\/dt>\n<dd><p>Each run is bounded: a limited number of attachments and files are processed per run, nothing is loaded into\nmemory in full, and the screen tells you when the window was partial so you can continue manually. There is no\nbackground job and no cron.<\/p><\/dd>\n<dt id=\"privacy\"><h3>Privacy<\/h3><\/dt>\n<dd><p>Everything runs locally inside your own admin request. Filenames, paths and results are never uploaded, never sent\nto any external service, never logged and never stored in the database. The plugin makes no network requests and\ncollects no telemetry.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.1<\/h4>\n\n<ul>\n<li>The results screen now ends with a short \"What to do next\" guidance block: what missing files, orphan candidates\nand unknown files each mean, and the safe order of actions (backup first, restore files, verify candidates by\nhand, leave unknown files alone).<\/li>\n<li>The first screen explains what will be checked and that nothing will be changed; the scan-window fields moved\nunder \"Advanced: scan window\". Defaults and scan behaviour are unchanged.<\/li>\n<li>Honest result presentation: when a table shows the first 200 rows the screen says so and points to the CSV; the\nsummary labels the derived count as \"counted, not listed\"; the scan-window term is explained in one line.<\/li>\n<li>A clean window is now reported as a success notice instead of three \"nothing to report\" lines - without claiming\nanything about the parts of the library that were not scanned.<\/li>\n<li>This readme and the listing now lead with the problem (images missing after a migration or restore) instead of\nthe implementation.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>First release: read-only report of Media Library files missing from disk and uploads files that no attachment\nclaims, with a conservative unknown group, a bounded scan window and a CSV export.<\/li>\n<\/ul>","raw_excerpt":"Images missing after a migration or restore? See exactly which Media Library files WordPress expects but cannot find on disk - and change nothing.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/bal.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/377492","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bal.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/bal.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/bal.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=377492"}],"author":[{"embeddable":true,"href":"https:\/\/bal.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/frutilabs"}],"wp:attachment":[{"href":"https:\/\/bal.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=377492"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/bal.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=377492"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/bal.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=377492"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/bal.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=377492"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/bal.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=377492"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/bal.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=377492"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}