GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Konvertieren Sie die Ausgabe des Baumbefehls in das Json-Format?

Gibt es eine bequeme Möglichkeit, die Ausgabe des *nix-Befehls „tree“ in das JSON-Format zu konvertieren?

Bearbeiten:
Ich glaube, ich habe mein Problem nicht gut genug beschrieben. Mein Ziel ist es, so etwas zu konvertieren:

.
|-- dir1
|   |-- dirA
|   |   |-- dirAA
|   |   `-- dirBB
|   `-- dirB
`-- dir2
    |-- dirA
    `-- dirB

in:

{"dir1" : [{"dirA":["dirAA", "dirAB"]}, "dirB"], "dir2": ["dirA", "dirB"]}

Akzeptierte Antwort:

Versuch 1

Eine Lösung, die nur Perl verwendet und eine einfache Hash-von-Hashes-Struktur zurückgibt. Vor dem
OP geklärtes Datenformat von JSON.

#! /usr/bin/perl

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->{$_};
    }
}

File::Find Das Modul funktioniert ähnlich wie das Unix-Modul find Befehl. Der JSON Modul nimmt Perl-Variablen und konvertiert sie in JSON.

find({wanted => &process_dir, no_chdir => 1 }, ".");

Iteriert die Dateistruktur ab dem aktuellen Arbeitsverzeichnis und ruft die Subroutine process_dir auf für jede Datei/Verzeichnis unter „.“ und no_chdir Perl anweisen, kein chdir() auszugeben für jedes gefundene Verzeichnis.

process_dir gibt zurück, wenn die gegenwärtig untersuchte Datei kein Verzeichnis ist:

return if !-d $File::Find::name;

Dann holen wir uns eine Referenz auf den vorhandenen Hash %$dirs in $ref , teilen Sie den Dateipfad um / auf und Schleife mit for Hinzufügen eines neuen Hash-Schlüssels für jeden Pfad.

Eine Verzeichnisstruktur erstellen, wie es slm getan hat:

mkdir -p dir{1..5}/dir{A,B}/subdir{1..3}

Die Ausgabe ist:

{
   "." : {
      "dir3" : {
         "dirA" : {
            "subdir2" : {},
            "subdir3" : {},
            "subdir1" : {}
         },
         "dirB" : {
            "subdir2" : {},
            "subdir3" : {},
            "subdir1" : {}
         }
      },
      "dir2" : {
         "dirA" : {
            "subdir2" : {},
            "subdir3" : {},
            "subdir1" : {}
         },
         "dirB" : {
            "subdir2" : {},
            "subdir3" : {},
            "subdir1" : {}
         }
      },
      "dir5" : {
         "dirA" : {
            "subdir2" : {},
            "subdir3" : {},
            "subdir1" : {}
         },
         "dirB" : {
            "subdir2" : {},
            "subdir3" : {},
            "subdir1" : {}
         }
      },
      "dir1" : {
         "dirA" : {
            "subdir2" : {},
            "subdir3" : {},
            "subdir1" : {}
         },
         "dirB" : {
            "subdir2" : {},
            "subdir3" : {},
            "subdir1" : {}
         }
      },
      "dir4" : {
         "dirA" : {
            "subdir2" : {},
            "subdir3" : {},
            "subdir1" : {}
         },
         "dirB" : {
            "subdir2" : {},
            "subdir3" : {},
            "subdir1" : {}
         }
      }
   }
}

Versuch 2

Okay, jetzt mit anderer Datenstruktur…

#! /usr/bin/perl

use warnings;
use strict;
use JSON;

my $encoder = JSON->new->ascii->pretty;   # ascii character set, pretty format
my $dirs;                                 # used to build the data structure

my $path=$ARGV[0] || '.';                 # use the command line arg or working dir

# Open the directory, read in the file list, grep out directories and skip '.' and '..'
# and assign to @dirs
opendir(my $dh, $path) or die "can't opendir $path: $!";
my @dirs = grep { ! /^[.]{1,2}/ && -d "$path/$_" } readdir($dh);
closedir($dh);

# recurse the top level sub directories with the parse_dir subroutine, returning
# a hash reference.
%$dirs = map { $_ => parse_dir("$path/$_") } @dirs;

# print out the JSON encoding of this data structure
print $encoder->encode($dirs);

sub parse_dir {
    my $path = shift;    # the dir we're working on

    # get all sub directories (similar to above opendir/readdir calls)
    opendir(my $dh, $path) or die "can't opendir $path: $!";
    my @dirs = grep { ! /^[.]{1,2}/ && -d "$path/$_" } readdir($dh);
    closedir($dh);

    return undef if !scalar @dirs; # nothing to do here, directory empty

    my $vals = [];                            # set our result to an empty array
    foreach my $dir (@dirs) {                 # loop the sub directories         
        my $res = parse_dir("$path/$dir");    # recurse down each path and get results

        # does the returned value have a result, and is that result an array of at 
        # least one element, then add these results to our $vals anonymous array 
        # wrapped in a anonymous hash
        # ELSE
        # push just the name of that directory our $vals anonymous array
        push(@$vals, (defined $res and scalar @$res) ? { $dir => $res } : $dir);
    }

    return $vals;  # return the recursed result
}

Und dann das Skript auf der vorgeschlagenen Verzeichnisstruktur ausführen…

./tree2json2.pl .
{
   "dir2" : [
      "dirB",
      "dirA"
   ],
   "dir1" : [
      "dirB",
      {
         "dirA" : [
            "dirBB",
            "dirAA"
         ]
      }
   ]
}

Ich fand es verdammt schwierig, das richtig zu machen (insbesondere angesichts der Logik „Hash, wenn Unterverzeichnisse, Array, wenn nicht, OH, ES SEI DENN oberste Ebene, dann nur Hashes“).
Ich wäre also überrascht, wenn Sie dies mit sed tun könnten / awk … aber dann
Stephane hat sich das bestimmt noch nicht angeschaut 🙂

Verwandte:Wie funktioniert der Exit-Befehl auf einem Unix-Terminal?
Linux
  1. 12 Beispiele für Ausgabeformatoptionen für UNIX-/Linux-Zeitbefehle

  2. Pinky-Befehlsbeispiele in Linux

  3. Anzeigen der vollständigen Ausgabe des PS-Befehls

  4. Gerätenummer in der Ausgabe des Stat-Befehls

  5. Konvertieren Sie die Ausgabe von bash `ls` in ein json-Array

Ccat – Cat-Befehlsausgabe einfärben

Zeigen Sie die Ping-Befehlsausgabe im Diagrammformat mit Gping an

iftop-Befehl unter Linux

Baumbefehl in Linux

lsblk-Befehl unter Linux

Beispiele für Linux-Echo-Befehle