Come estrarre una cartella specificata da una directory ricorsiva, eliminare le altre?


10

Ho questo tipo di albero di directory che si ottiene dalla decompressione di un file zip:

x -> y -> z -> esegui -> FILE E DIRECTORIES QUI

Quindi ci sono 4 directory, 3 delle quali sono vuote di file (x, y, z) e contengono solo 1 sottodirectory, e c'è la directory che mi interessa, chiamata " run ".

Voglio spostare la directory "run" stessa (incluso tutto all'interno) nella posizione "root" dove ho decompresso (cioè dove si trova "x", ma non all'interno di "x").

Presupposti: esiste una cartella denominata "run", ma non so quante directory dovrò "cd" per arrivarci (potrebbe essere 3 (x, y, z), potrebbe essere 10 o più. sono anche sconosciuti e non devono essere x, y, z ecc.).

Come posso farlo? Ho provato molte varianti di questa domanda ma tutte hanno fallito.


1
Temo che l'immagine non sia molto chiara, no. Si prega di non pubblicare schermate di testo . Invece, incolla il testo direttamente nella tua domanda e usa gli strumenti di formattazione . Non riesco nemmeno a leggere il nome della directory nella tua foto. Tutto quello che vedo è una sfocatura blu pallida.
terdon

Risposte:


14

che dire

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

dove

  • / percorso / a / X è la directory di destinazione
  • si parte da questo stesso posto.
  • quindi usa un'altra risposta per rimuovere le directory vuote.

(in una nota a margine c'è --junk-pathsun'opzione in zip, sia in zippare che decomprimere)


7

Lo farei bashusando globstar. Come spiegato 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.

Quindi, per spostare la directory nella directory rundi livello superiore xe quindi eliminare il resto, puoi fare:

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

Il shoptcomando abilita l' globstaropzione. Il mv x/**/run/ x/sposterà tutta la sottodirectory run(nota che questo funziona solo se v'è una sola rundirectory) xe la findcancellerà le directory vuote.

Se lo desideri, potresti fare tutto nella shell con il globbing esteso, ma preferisco la rete di sicurezza find -emptyper essere sicuro che nessuna directory non vuota venga eliminata. Se non ti interessa, puoi usare:

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

6

Sicuramente più dettagliato, ma facendo il lavoro in un solo passaggio:

Supponendo che tu abbia installato 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]))

Come usare

  1. Copia lo script in un file vuoto, salvalo come get_folder.py
  2. Eseguilo con la directory principale (contenente le tue cose decompresse) e il nome della cartella da "sollevare" come argomenti:

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

Ed è fatto:

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine


Questa è una soluzione molto interessante, ma preferisco non usare alcun script Python per vari motivi. Grazie mille!
Idos,

Nessun problema. Forse è utile a chiunque altro. Curioso del perché, però? Sono abbastanza sicuro che molte applicazioni utilizzino già Python.
Jacob Vlijm,

Soprattutto dal momento che posizionare il file .py ovunque sarà problematico in quanto devo supporre che sia nello stesso posto per ogni macchina Linux che eseguirà il mio script (e il mio script viene eseguito su molte piattaforme).
Idos,

@Idos solo curioso, quali piattaforme? Python è abbastanza diffuso. Non penso che sia installato su Mac OS X per impostazione predefinita, ma la maggior parte delle distribuzioni Linux ce l'hanno
Sergiy Kolodyazhnyy

4

Soluzione Perl

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

Il modo in cui funziona è semplice: la find()subroutine attraverserà ricorsivamente l'albero di directory specificato, troverà la directory il cui nome è rune lo inserirà nella matrice dei nomi di file desiderati. In questo caso, supponiamo che dovrebbe esserci un solo file nell'elenco, quindi una volta completato il comando, usiamo dirmove()dal File::Copy::Recursivemodulo e lo spostiamo nella directory di lavoro corrente da cui è stato chiamato lo script. Quindi nel tuo caso lo chiameresti dalla directory principale a x.

Albero di directory originale:

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

Risultato:

$ ~/find_dir.pl .  
$ tree 
.
├── levelone
│   └── leveltwo
│       └── levelthree
└── run
    ├── file1
    ├── file2
    └── file3
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.