Как мне выяснить, используется ли файл / вызывается другим?

#perl #bash #scripting

#perl #bash #сценарии

Вопрос:

В настоящее время я учусь на втором курсе колледжа, поэтому мои навыки программирования и знания не так сильны, как мне хотелось бы. Я прохожу стажировку в компании по веб-разработке во время летних каникул и полностью справляюсь с первой задачей, которая была мне поручена. Вот почему я здесь прошу некоторой помощи.

В основной папке есть много вложенных папок, и в каждой вложенной папке находится много файлов .js .cs и .php — около 1000 файлов. Но около 300 не используются. Мне нужно открыть каждую из вложенных папок и посмотреть, используется ли какой-либо из этих файлов / вызывается какими-либо другими файлами. Если это не так, мне нужно сохранить местоположение неиспользуемого файла в текстовом файле.

Я провел некоторое исследование и выяснил, что команда grep -r filename * делает именно это, но в командной строке я не могу понять, как перебирать папки и изменять имя файла на основе содержимого внутри папок. Моя рабочая станция находится в Windows с установленным Cygwin.

Комментарии:

1. Ну, первое, что нужно узнать, это как помечать свои записи тегами свойств SO. Это не вопрос PHP, JS, CSS или Eclipse!

2. глядя на теги, я не понимаю, на каком языке вы хотите или должны это написать.

3. Я добавил повторный тег, который включает bash и perl , поскольку я думаю, что это будет окончательный маршрут.

Ответ №1:

 echo file,count >results.csv
for f in $(find . -name *.js -o -name *.cs -o -name *.php)
do
    echo $f,$(grep -cr $(basename $f) *) >> results.csv
done
  

это даст вам CSV-файл, подобный этому, с указанием количества ссылок на каждый файл.

 file,count
file1,3
file2,1
file3,0
  

отредактировано, чтобы удалить путь к файлу перед повторным использованием

Комментарии:

1. единственная проблема в том, что это не обрабатывает ссылки на пути (что, вероятно, будет очень сложно выяснить). Предполагается, что каждая ссылка на файлы, которые могут существовать в другом файле, ссылается на него по пути из каталога, в котором вы находитесь в данный момент… чтобы сделать это немного более точным, вам нужно удалить начальный путь к файлу и использовать grep только по имени файла…

Ответ №2:

Разве для этого не требуется двойной цикл? (Большое О2). Вы должны искать в каждом файле каждый экземпляр файла в нем.

Я бы использовал Perl вместо Awk или BASH (хотя это можно сделать в BASH).

 #! /usr/bin/env perl

use warnings;
use strict;
use feature qw(say);

use File::Find;     #Not crazy about File::Find, but it's a standard module
use File::Basename;

my %fileHash;
my @dirs = qw(foo bar barfu fufu barbar);   #List of the directories you're searching

#Finds the name of all the files. Include ALL files and not just .php, etc.

find(amp;wanted, @dirs);

sub wanted {
    next if (-d $File::Find::name); #Skip directories
    $fileHash{$File::Find::name} = 0;       #Number of times file is referenced
}

# Outer Loop: Foreach file you have to parse

foreach my $fileName (keys %fileHash) {

    # We don't have to grep anything except those below.
    (my $suffix = $fileName) =~ s/.*.//;
    next unless ($suffix eq ".js" or $suffix eq ".cs" or $suffix eq ".php");

    #Slurp up file in an array. That way, we can use the grep command
    open (FILE, $fileName) or die qq(Can't open "$fileName" for readingn);
    my @lines = <FILE>;
    close FILE;

    # Now, look for each and every file you've got in that directory tree
    # in this particular file. This is an inner loop

    foreach my $fileToFind (keys %fileHash) {
        my $basename = basename($fileToFind);

        # If any lines in the file contain the file name, increment the hash.
        if (grep /$basename/, @lines) {
            $fileHash{$fileToFind}  = 1;
        }   
    }   
}   


#Now just print out those files who never got incremented (i.e. never referenced)
foreach my $fileName (keys %FileHash) {
    next if ($fileHash{$fileName} != 0);
    say "File: $fileHash{$fileName}"
}   
  

Я использую короткий путь поиска только базового имени файла, а не полного имени. Теоретически, я должен искать как его полное имя из корня, так и его имя в связи с самим файлом. Однако мне слишком лень делать это прямо сейчас. Скорее всего, вам не нужно беспокоиться об этом.

Ответ №3:

фух, сложно. По крайней мере, если вам нужно учитывать бит «используется».

В случае .cs у вас могут быть инструкции import, которые не позволят вам легко определить, используется ли файл. Импорт может работать на уровне пакета, если я не ошибаюсь (будучи больше специалистом по Java …).

И я предполагаю, что это ухудшается для файлов JavaScript и php.

Возможно, вам следует спросить, почему этот отчет ценен в первую очередь?

Ответ №4:

Это всего лишь черновик, вам нужно изучить все команды и использовать свою собственную логику…

 for file in $(find -type f -name *.extension); do
    grep -Rl $file /in/path
done > /tmp/myfiles
  

Комментарии:

1. Проблема с этим: если файлов слишком много, командная строка заполнится, и вы не сможете найти все файлы в автоматическом режиме. Лучше передать find в оператор while.