¿Cómo extraer una carpeta con un nombre específico de un directorio recursivo, eliminar los demás?

10

Tengo este tipo de árbol de directorios que se obtiene al descomprimir un archivo zip:

x -> y -> z -> ejecutar -> ARCHIVOS Y DIRECTORIOS AQUÍ

Así que hay 4 directorios, 3 de los cuales están vacíos de archivos (x, y, z) y solo contienen 1 subdirectorio, y existe el directorio en el que estoy interesado, llamado " run ".

Quiero mover el directorio "ejecutar" (incluyendo todo lo que está dentro) a la ubicación "raíz" donde descomprimí (es decir, donde está "x", pero no dentro de "x").

Suposiciones: existe una carpeta llamada "ejecutar", pero no sé cuántos directorios tendré que "cd" para acceder (podría ser 3 (x, y, z), podría ser 10 o más. Los nombres También son desconocidos y no tienen que ser x, y, z, etc.

¿Cómo puedo lograr esto? Intenté muchas variaciones de esta pregunta pero todas fallaron.

Idos
fuente
1
Me temo que la imagen no es muy clara, no. No publique capturas de pantalla de texto . En su lugar, pegue el texto directamente en su pregunta y use las herramientas de formato . Ni siquiera puedo leer el nombre del directorio en tu imagen. Todo lo que veo es un borroso azul oscuro.
terdon

Respuestas:

14

qué pasa

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

dónde

  • / ruta / a / X es su directorio de destino
  • comienzas desde este mismo lugar.
  • luego use otra respuesta para eliminar directorios vacíos.

(en una nota al margen hay una --junk-pathsopción en zip, ya sea al comprimir o descomprimir)

Archemar
fuente
7

Haría esto en bash, usando globstar. Como se explica en 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.

Entonces, para mover el directorio runal directorio de nivel superior xy luego eliminar el resto, puede hacer lo siguiente:

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

El shoptcomando habilita la globstaropción. Se mv x/**/run/ x/moverán los subdirectorios nombrados run(tenga en cuenta que esto solo funciona si solo hay un rundirectorio) xy findse eliminarán los directorios vacíos.

Si lo desea, puede hacer todo el proceso en el shell con globbing extendido, pero prefiero la red de seguridad find -emptypara asegurarme de que no se eliminen los directorios no vacíos. Si no te importa eso, puedes usar:

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

Definitivamente más detallado, pero hacer el trabajo en un solo paso:

Asumiendo que tienes Python instalado

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

Cómo utilizar

  1. Copie el script en un archivo vacío, guárdelo como get_folder.py
  2. Ejecútelo con el directorio raíz (que contiene sus cosas descomprimidas) y el nombre de la carpeta para "levantar" como argumentos:

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

Y ya está hecho:

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

Jacob Vlijm
fuente
Esta es una solución muy interesante, pero prefiero no usar ningún script de Python por varias razones. ¡Gracias!
Idos
No hay problema. Tal vez sea de utilidad para cualquier otra persona. ¿Curioso por qué? Estoy bastante seguro de que muchas aplicaciones ya usan Python.
Jacob Vlijm
Principalmente, ya que colocar el archivo .py en cualquier lugar será problemático, ya que debo suponer que está en el mismo lugar para cada máquina Linux que ejecutará mi script (y mi script se ejecuta en muchas plataformas).
Idos
@Idos solo curioso, ¿qué plataformas? Python está bastante extendido. No creo que esté instalado en Mac OS X de forma predeterminada, pero la mayoría de las distribuciones de Linux lo tienen
Sergiy Kolodyazhnyy
4

Solución 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");

La forma en que esto funciona es simple: la find()subrutina atravesará el árbol de directorios dado de forma recursiva, encontrará el directorio cuyo nombre es runy lo insertará en una matriz de nombres de archivos deseados. En este caso, suponemos que solo debe haber un archivo en la lista, por lo tanto, una vez que se completa el comando, lo usamos dirmove()desde el File::Copy::Recursivemódulo y lo movemos al directorio de trabajo actual desde el que se llamó el script. Así, en el caso de que le llamaremos a partir de directorio raíz para x.

Árbol de directorios original:

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

Resultado:

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