Wie extrahiere ich einen speziell benannten Ordner aus einem rekursiven Verzeichnis und lösche die anderen?

10

Ich habe diese Art von Verzeichnisbaum, der durch Entpacken einer Zip-Datei erhalten wird:

x -> y -> z -> run -> DATEIEN UND VERZEICHNISSE HIER

Es gibt also 4 Verzeichnisse, von denen 3 keine Dateien (x, y, z) enthalten und nur 1 Unterverzeichnis enthalten, und es gibt das Verzeichnis, an dem ich interessiert bin, mit dem Namen " run ".

Ich möchte das "run" -Verzeichnis selbst (einschließlich aller darin enthaltenen) an den "root" -Standort verschieben, an dem ich es entpackt habe (dh wo "x" ist, aber nicht innerhalb von "x").

Annahmen: Es gibt einen Ordner mit dem Namen "run", aber ich weiß nicht, wie viele Verzeichnisse ich "cd" haben muss, um dorthin zu gelangen (könnte 3 (x, y, z) sein, könnte 10 oder mehr sein. Die Namen sind ebenfalls unbekannt und müssen nicht x, y, z usw. sein.

Wie kann ich das erreichen? Ich habe viele Variationen dieser Frage ausprobiert , aber alle sind gescheitert.

Idos
quelle
1
Ich fürchte, das Bild ist nicht sehr klar, nein. Bitte poste keine Screenshots von Text . Fügen Sie stattdessen den Text direkt in Ihre Frage ein und verwenden Sie die Formatierungswerkzeuge . Ich kann nicht einmal den Verzeichnisnamen in Ihrem Bild lesen. Ich sehe nur eine dunkle blaue Unschärfe.
Terdon

Antworten:

14

wie wäre es mit

  find . -type d -name run -exec mv {} /path/to/X \;

wo

  • / path / to / X ist Ihr Zielverzeichnis
  • Sie starten an derselben Stelle.
  • Verwenden Sie dann eine andere Antwort, um leere Verzeichnisse zu entfernen.

( --junk-pathsNebenbei bemerkt gibt es eine Option in zip, entweder beim Zippen oder beim Entpacken)

Archemar
quelle
7

Ich würde dies in tun bash, mit globstar. Wie erklärt in man bash:

globstar
      If set, the pattern ** used in a pathname expansion con‐
      text will match all files and zero or  more  directories
      and  subdirectories.  If the pattern is followed by a /,
      only directories and subdirectories match.

Um das Verzeichnis runin das Verzeichnis der obersten Ebene zu verschieben xund den Rest zu löschen, haben Sie folgende Möglichkeiten:

shopt -s globstar; mv x/**/run/ x/  && find x/ -type d -empty -delete

Der shoptBefehl aktiviert die globstarOption. Das mv x/**/run/ x/verschiebt alle benannten Unterverzeichnisse run(beachten Sie, dass dies nur funktioniert, wenn es nur ein runVerzeichnis gibt) in xund findlöscht alle leeren Verzeichnisse.

Wenn Sie möchten, können Sie das Ganze in der Shell mit erweitertem Globbing ausführen, aber ich bevorzuge das Sicherheitsnetz find -empty, um sicherzustellen, dass keine nicht leeren Verzeichnisse gelöscht werden. Wenn Sie sich nicht darum kümmern, können Sie Folgendes verwenden:

shopt -s globstar; shopt -s extglob; mv x/**/run/ x/ && rm -rf x/!(run)
terdon
quelle
6

Auf jeden Fall ausführlicher, aber die Arbeit in einem Schritt erledigen:

Angenommen, Sie haben Python installiert

#!/usr/bin/env python3
import shutil
import os
import sys

dr = sys.argv[1]

for root, dirs, files in os.walk(dr):
    # find your folder "run"
    for pth in [d for d in dirs if d == sys.argv[2]]:
        # move the folder to the root directory
        shutil.move(os.path.join(root, pth), os.path.join(dr, pth))
        # remove the folder (top of the tree) from the directory
        shutil.rmtree(os.path.join(dr, root.replace(dr, "").split("/")[1]))

Wie benutzt man

  1. Kopieren Sie das Skript in eine leere Datei und speichern Sie es unter get_folder.py
  2. Führen Sie es mit dem Stammverzeichnis (das Ihre entpackten Inhalte enthält) und dem Namen des Ordners aus, der als Argumente "angehoben" werden soll:

    python3 /full/path/to/get_folder.py /full/path/to/folder_containing_unzipped_dir run
    

Und es ist geschafft:

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein

Jacob Vlijm
quelle
Dies ist eine sehr interessante Lösung, aber ich bevorzuge aus verschiedenen Gründen, kein Python-Skript zu verwenden. Danke tho!
Idos
Kein Problem. Vielleicht ist es für andere von Nutzen. Neugierig warum? Ich bin mir ziemlich sicher, dass viele Anwendungen bereits Python verwenden.
Jacob Vlijm
Hauptsächlich, da das Platzieren der .py-Datei an einer beliebigen Stelle problematisch ist, da ich davon ausgehen muss, dass sie sich für jeden Linux-Computer, auf dem mein Skript ausgeführt wird, an derselben Stelle befindet (und mein Skript auf vielen Plattformen ausgeführt wird).
Idos
@ Idos nur neugierig, welche Plattformen? Python ist ziemlich weit verbreitet. Ich glaube nicht, dass es standardmäßig unter Mac OS X installiert ist, aber die meisten Linux-Distributionen haben es
Sergiy Kolodyazhnyy
4

Perl-Lösung

#!/usr/bin/env perl
use strict;
use warnings;
use File::Find;
use File::Copy::Recursive qw(dirmove);

my @wanted;
find(sub{ -d $_ && $_ eq "run" && push @wanted,$File::Find::name}, $ARGV[0]);
dirmove("$wanted[0]","./run");

Die Funktionsweise ist einfach: Die find()Subroutine durchläuft den angegebenen Verzeichnisbaum rekursiv, sucht das Verzeichnis mit dem Namen runund verschiebt es in ein Array gewünschter Dateinamen. In diesem Fall wird davon ausgegangen, dass nur eine Datei in der Liste enthalten sein sollte. Sobald der Befehl abgeschlossen ist, verwenden wir ihn dirmove()vom File::Copy::RecursiveModul und verschieben ihn in das aktuelle Arbeitsverzeichnis, aus dem das Skript aufgerufen wurde. In Ihrem Fall würden Sie es also vom übergeordneten Verzeichnis nach aufrufen x.

Ursprünglicher Verzeichnisbaum:

$ tree                                                                                                                   
.
└── levelone
    └── leveltwo
        └── levelthree
            └── run
                ├── file1
                ├── file2
                └── file3

Ergebnis:

$ ~/find_dir.pl .  
$ tree 
.
├── levelone
│   └── leveltwo
│       └── levelthree
└── run
    ├── file1
    ├── file2
    └── file3
Sergiy Kolodyazhnyy
quelle