Преобразуйте содержимое каталога и его подкаталогов в JSON - PullRequest
2 голосов
/ 05 января 2020

У меня есть следующий perl скрипт из этого вопроса об обмене стека, который преобразует содержимое каталога в JSON.

use File::Find; 
use JSON; 
use strict; 
use warnings; 

my $dirs={}; 
my $encoder = JSON->new->ascii->pretty; 
find({wanted => \&process_dir, no_chdir => 1 }, "."); 

print $encoder->encode($dirs); 
sub process_dir { 
    return if !-d $File::Find::name; 
    my $ref=\%$dirs; 

    for(split(/\//, $File::Find::name)) { 
        $ref->{$_} = {} 
        if(!exists $ref->{$_}); 
        $ref = $ref->{$_}; 
  } 
}

Я запускаю скрипт с использованием Termux на Android 6.0.

Рассмотрим следующий каталог:

.
 |--server .
 |         | - File 1.tmp
 |         | - File 2.sql
 |         | - File 3.sql
 |-- js .
 |         | - File 1.js
 |         | - File 2.js
 |         | - File 3.js
 | -css .
 |         | - File 1.js
 |         | - File 2.js
 |         | - File 3.js
 | -assets .
 |         | - Font-awesome 
 |         |        .
 |         |        | - webfont.
 |         |        |          | - File 2.woff
 |         |        |          | - File 2.woff
 |         |        |          | - File 3.woff
 |         |        | - css .
 |         |        |       | - File 2.css
 |         |        |       | - File 2.css
 |         |        |       | - File 3.css
 |         | - Fonts
 |         |        | - ps  .
 |         |        |       | - File 2.woff
 |         |        |       | - File 2.css
 |         |        |       | - File 3.txt
 |         | - images 
 |         |        | - File 1.png
 |         |        | - File 2.png
 |         |        |   - File 3.svg

Сценарий возвращает следующее, если я запустите его в указанном выше каталоге:

{
"." : {
      "server" : {},                               
      "js" : {},
      "css" : {},
      "assets" : {
         "fonts" : {                                       
            "ps":{}
         },
         "images" : {},
         "font-awesome" : {
            "css" :{},                                     
            "webfonts" : {}
         }
      }                                 
     }                                            
    }

Я пытаюсь отредактировать скрипт, чтобы дополнительно включить файлы в каждом подкаталоге в виде массива Js (если это возможно, используя perl + JSON Модуль, или просто Perl)

Например [Редактировать]

{
"." : {
      "server" : {"Files": ["File1", "File2", "File n"]},
      /* Or just "server" : ["File1", "File2", "File n"], ... */
      "js" : {"Files": ["File1", "File2", "File n"]},                                
      "assets" : {
         "fonts" : {                                       
             "ps":{"Files": ["File1", "File2", "File n"]}
          },
         "images" : {"Files": ["File1", "File2", "File n"]},
         "font-awesome" : {
         "css" : {"Files": ["File1", "File2", "File n"]}                    
         "webfonts" : {"Files": ["File1", "File2", "File n"]}
     }
  }     
 }                                            
}

Это достижимо? Если так, как я должен go об этом? Я относительно новичок в perl, и мне трудно обдумать это.

Ответы [ 3 ]

2 голосов
/ 06 января 2020

Я попробовал и решил переместить имена файлов в запись с помощью специального ключа __files__. Это сломается, если у вас есть каталог с таким именем.

use File::Find; 
use JSON; 
use strict; 
use warnings;
use 5.12.0;
use Data::Dumper;
my $dirs={}; 
my $encoder = JSON->new->ascii->pretty; 
find({wanted => \&process_dir, no_chdir => 1 }, "."); 
print $encoder->encode($dirs); 
sub process_dir { 
    my $full_name = $File::Find::name;
    my $ref=$dirs; 
    if (-d $full_name ) {
        for (split(/\//, $full_name)) {  # only directories
            $ref->{$_} ||= {};  # create the next level if it does not exist
            $ref = $ref->{$_};  # move to the next level         
        }
    } else {
        for (split(/\//, $full_name)){  # n directories and 1 filename
            if (exists $ref->{$_}) {    # it's a directory
                $ref = $ref->{$_}
            } else {
                push @{$ref->{__files__}}, $_;  # it's a filename
                # $ref->{$_} = '_is_file_';
            }
        }
    }
}
0 голосов
/ 06 января 2020

Другой вариант кода: файлы являются элементами массива , каталоги являются га sh с ключом имени каталога и содержимое в виде массива , затем преобразуется в JSON формат

use strict;
use warnings;

use JSON;

my $data;

my $dir = shift // '.';    # // correct website highlighting

$data->{$dir} = traverse($dir, $dir);

my $encoder = JSON->new->ascii->pretty; 

print $encoder->encode($data); 


sub traverse {
    my $dir  = shift;
    my $name = shift;

    my($dh,@data,%ret);

    opendir($dh, $dir)
        or die "Could not open $dir";


    while( my $name = readdir($dh) ) {
        next if $name eq '.' or $name eq '..';

        my $path = "$dir/$name";

        push @data, traverse($path,$name) if -d $path;
        push @data, $name                 if -f $path;
    }

    closedir $dh;

    return ( $name => \@data );
}
0 голосов
/ 06 января 2020

Следующий фрагмент кода помещает структуру каталогов в ha sh, а затем преобразует ее в JSON формат

use strict;
use warnings;

use JSON;

my $data;

my $dir = shift // '.';   # // correct website highlighting

$data->{$dir} = traverse($dir);

my $encoder = JSON->new->ascii->pretty; 

print $encoder->encode($data); 

sub traverse {
    my $dir = shift;

    my($dh,$data);

    $data->{'files'} = ();

    opendir($dh, $dir)
        or die "Could not open $dir";

    while( my $name = readdir($dh) ) {
        next if $name eq '.' or $name eq '..';

        my $path = "$dir/$name";

        $data->{$name} = traverse($path) if -d $path;
        push @{$data->{'files'}}, $name  if -f $path;
    }

    closedir $dh;

    return $data;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...