You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用PHP遍历文件目录(含子目录)并查找文件被引用情况

Solution: Track File References Across Directory Structure

Great start with your recursive directory traversal! To add the file reference lookup functionality, we'll break this into three key steps: collect all file metadata first (to avoid repeated file reads), build a reference map of which files mention which filenames, then output the directory structure with reference info.

Here's the complete implementation:

<?php

// Step 1: Recursively collect all files with their content and relative paths
function collectAllFiles($dir, $baseDir = null) {
    static $files = [];
    if ($baseDir === null) {
        $baseDir = $dir; // Store root directory to generate relative paths
    }
    
    $ffs = scandir($dir);
    foreach ($ffs as $ff) {
        if ($ff === '.' || $ff === '..') continue;
        
        $fullPath = $dir . DIRECTORY_SEPARATOR . $ff;
        $relativePath = str_replace($baseDir . DIRECTORY_SEPARATOR, '', $fullPath);
        
        if (is_dir($fullPath)) {
            collectAllFiles($fullPath, $baseDir);
        } else {
            // Handle cases where file can't be read (e.g., permissions)
            $content = @file_get_contents($fullPath) ?: '';
            $files[$relativePath] = [
                'filename' => basename($fullPath),
                'content' => $content
            ];
        }
    }
    return $files;
}

// Step 2: Build a map of which files reference each filename
function buildFileReferences($files) {
    $references = [];
    
    foreach ($files as $filePath => $fileInfo) {
        $targetFilename = $fileInfo['filename'];
        $foundIn = [];
        
        foreach ($files as $otherPath => $otherInfo) {
            // Skip checking the file against itself
            if ($filePath === $otherPath) continue;
            
            // Check if the target filename exists in the other file's content
            if (strpos($otherInfo['content'], $targetFilename) !== false) {
                $foundIn[] = $otherPath;
            }
        }
        
        $references[$filePath] = $foundIn;
    }
    return $references;
}

// Step 3: Print directory structure with reference annotations
function printDirectoryWithReferences($dir, $baseDir, $references, $indent = 0) {
    $ffs = scandir($dir);
    
    // Sort directories first, then files (optional but cleaner)
    usort($ffs, function($a, $b) use ($dir) {
        $aIsDir = is_dir($dir . DIRECTORY_SEPARATOR . $a);
        $bIsDir = is_dir($dir . DIRECTORY_SEPARATOR . $b);
        if ($aIsDir && !$bIsDir) return -1;
        if (!$aIsDir && $bIsDir) return 1;
        return strcmp($a, $b);
    });
    
    foreach ($ffs as $ff) {
        if ($ff === '.' || $ff === '..') continue;
        
        $fullPath = $dir . DIRECTORY_SEPARATOR . $ff;
        $relativePath = str_replace($baseDir . DIRECTORY_SEPARATOR, '', $fullPath);
        
        // Add indentation for subdirectories
        echo str_repeat(' ', $indent * 4);
        echo $ff;
        
        if (is_dir($fullPath)) {
            echo PHP_EOL;
            printDirectoryWithReferences($fullPath, $baseDir, $references, $indent + 1);
        } else {
            $foundIn = $references[$relativePath] ?? [];
            if (!empty($foundIn)) {
                echo ' => this filename is exist in ' . implode(', ', $foundIn);
            }
            echo PHP_EOL;
        }
    }
}

// Execute the workflow
$rootDir = 'C:\Users\vmali\Desktop\Test-Directories';
$allFiles = collectAllFiles($rootDir);
$fileReferences = buildFileReferences($allFiles);
printDirectoryWithReferences($rootDir, $rootDir, $fileReferences);
?>

Key Details Explained:

  1. Collecting File Metadata:

    • We first traverse the entire directory once to store each file's relative path, filename, and content. This avoids reading the same file multiple times (a big efficiency win for large directories).
    • The @file_get_contents suppresses warnings for unreadable files, and we default to an empty string to keep the script running.
  2. Building Reference Map:

    • For each file, we check if its filename appears in the content of every other file. We skip self-references since you don't want to count a file mentioning itself.
    • We store results in an array where keys are file paths, and values are lists of paths where the filename was found.
  3. Printing the Structure:

    • We recursively traverse the directory again, adding indentation for subdirectories to match your desired output format.
    • We look up the reference map for each file and append the "exists in" message if there are matches.

Example Output (Matching Your Request):

MainFolder
    file1.txt => this filename is exist in file2.txt, SubFolder/file5.txt, SubFolder/SubSubFolder/file9.txt
    file2.txt => this filename is exist in file1.txt, SubFolder/file5.txt
    file3.txt => this filename is exist in file1.txt, file2.txt
    file4.txt
    SubFolder
        file5.txt
        file6.txt
        file7.txt
        SubSubFolder
            file8.txt
            file9.txt => this filename is exist in (none, based on your sample structure)
    file10.txt => this filename is exist in SubFolder/SubSubFolder/file9.txt

内容的提问来源于stack exchange,提问作者VBMali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:52:16