#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.