Jak wyodrębnić konkretnie nazwany folder z katalogu rekurencyjnego, usunąć pozostałe?


10

Mam tego rodzaju drzewo katalogów uzyskane z rozpakowania pliku zip:

x -> y -> z -> run -> PLIKI I DIRECTORIES TUTAJ

Są więc 4 katalogi, z których 3 są puste z plików (x, y, z) i zawierają tylko 1 podkatalog, i jest katalog, który mnie interesuje, o nazwie „ uruchom ”.

Chcę przenieść sam katalog „run” (w tym wszystko wewnątrz) do lokalizacji „root”, w której rozpakowałem (tj. Gdzie jest „x”, ale nie wewnątrz „x”).

Założenia: Nie istnieje folder o nazwie „run”, ale nie wiem, jak wiele katalogów będę musiał „cd”, aby dostać się do niego (może być 3 (x, y, z), może być 10 lub więcej nazw. są również nieznane i nie muszą być x, y, z itp.).

Jak mogę to osiągnąć? Próbowałem wielu odmian tego pytania, ale wszystkie zawiodły.


1
Obawiam się, że obraz nie jest bardzo wyraźny, nie. Nie publikuj zrzutów ekranu z tekstem . Zamiast tego wklej tekst bezpośrednio do pytania i użyj narzędzi formatujących . Nie mogę nawet odczytać nazwy katalogu na twoim zdjęciu. Widzę tylko niewyraźne niebieskie rozmycie.
— terdon

Odpowiedzi:


14

co powiesz na

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

gdzie

  • / path / to / X to katalog docelowy
  • zaczynasz z tego samego miejsca.
  • następnie użyj innej odpowiedzi, aby usunąć puste katalogi.

(na bocznej notatce jest --junk-pathsdostępna opcja zip, podczas zipowania lub rozpakowywania)


7

Zrobiłbym to bashza pomocą globstar. Jak wyjaśniono w 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.

Aby przenieść katalog rundo katalogu najwyższego poziomu x, a następnie usunąć resztę, możesz:

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

shoptKomenda umożliwia globstaropcję. mv x/**/run/ x/Ruszy żadnych podkatalogów nazwanych run(zauważ, że to działa tylko wtedy, gdy istnieje tylko jeden runkatalog) do xi findusunie żadnych pustych katalogów.

Możesz zrobić wszystko w powłoce z rozszerzonym globowaniem, jeśli chcesz, ale wolę siatkę bezpieczeństwa, find -emptyaby upewnić się, że żadne niepuste katalogi nie zostaną usunięte. Jeśli Cię to nie obchodzi, możesz użyć:

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

6

Zdecydowanie bardziej szczegółowy, ale wykonujący pracę w jednym kroku:

Zakładając, że masz zainstalowany Python

#!/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]))

Jak używać

  1. Skopiuj skrypt do pustego pliku i zapisz go jako get_folder.py
  2. Uruchom go z katalogiem głównym (zawierającym rozpakowane pliki) i nazwą folderu, aby „podnieść” jako argumenty:

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

I to jest zrobione:

wprowadź opis zdjęcia tutaj

wprowadź opis zdjęcia tutaj


To bardzo interesujące rozwiązanie, ale z różnych powodów wolę nie używać żadnego skryptu Pythona. Dziękuję ci!
— Idos,

Nie ma problemu. Może przyda się każdemu innemu. Ciekawe dlaczego? Jestem pewien, że wiele aplikacji już używa Pythona.
— Jacob Vlijm,

Głównie odkąd umieszczenie pliku .py w dowolnym miejscu będzie problematyczne, ponieważ muszę założyć, że znajduje się on w tym samym miejscu dla każdej maszyny linuxowej, która będzie uruchamiała mój skrypt (a mój skrypt działa na wielu platformach).
— Idos,

@Idos tylko ciekawy, które platformy? Python jest dość rozpowszechniony. Nie sądzę, że jest domyślnie zainstalowany na Mac OS X, ale większość dystrybucji Linuksa go ma
— Sergiy Kolodyazhnyy

4

Rozwiązanie Perla

#!/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");

Sposób działania jest prosty: find()podprogram przejdzie rekurencyjnie do podanego drzewa katalogów, znajdzie katalog o nazwie runi wrzuci go do tablicy poszukiwanych nazw plików. W tym przypadku zakładamy, że na liście powinien znajdować się tylko jeden plik, dlatego po zakończeniu polecenia korzystamy dirmove()z File::Copy::Recursivemodułu i przenosimy go do bieżącego katalogu roboczego, z którego został wywołany skrypt. Zatem w twoim przypadku wywołałbyś go z katalogu nadrzędnego do x.

Oryginalne drzewo katalogów:

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

Wynik:

$ ~/find_dir.pl .  
$ tree 
.
├── levelone
│   └── leveltwo
│       └── levelthree
└── run
    ├── file1
    ├── file2
    └── file3
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.