将目录及其子目录的内容转换为 JSON

Convert the contents of directory and its subdirectories to JSON

我有以下来自 this 堆栈交换问题的 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->{$_}; 
  } 
}

我是 运行 在 Android 6.0 上使用 Termux 的脚本。

考虑以下目录:

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

脚本returns如果我在上面的目录中执行它如下:

{
"." : {
      "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"]}
     }
  }     
 }                                            
}

这可以实现吗?如果是这样,我应该怎么做?我对 perl 比较陌生,我很难理解这个问题。

我试了一下,决定将文件名移动到具有特殊键 __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_';
            }
        }
    }
}

下面一段代码将目录结构放入hash,然后转换成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;
}

代码的其他变体:文件是数组元素目录散列 关键目录名内容为数组,然后转换为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 );
}