Bagaimana cara mengekstrak folder bernama khusus dari direktori rekursif, menghapus yang lain?

10

Saya memiliki jenis pohon direktori yang diperoleh dari membuka ritsleting file zip:

x -> y -> z -> run -> FILE DAN DIREKTUR DI SINI

Jadi ada 4 direktori, 3 di antaranya kosong dari file (x, y, z) dan hanya berisi 1 sub-direktori, dan ada direktori yang saya minati, bernama " run ".

Saya ingin memindahkan direktori "run" itu sendiri (termasuk semua yang ada di dalamnya) ke lokasi "root" tempat saya membuka ritsleting (yaitu di mana "x" berada, tetapi tidak di dalam "x").

Asumsi: Ada ada folder bernama "run", tapi saya tidak tahu berapa banyak direktori saya harus "cd" untuk sampai ke sana (bisa 3 (x, y, z), bisa 10 atau lebih Nama-nama. juga tidak dikenal dan tidak harus x, y, z dll).

Bagaimana saya bisa mencapai ini? Saya mencoba banyak variasi pertanyaan ini tetapi semuanya gagal.

Idos
sumber
1
Saya khawatir gambarnya tidak terlalu jelas, tidak. Tolong jangan memposting tangkapan layar teks . Alih-alih, tempel teks langsung ke pertanyaan Anda dan gunakan alat pemformatan . Saya bahkan tidak bisa membaca nama direktori di gambar Anda. Yang saya lihat adalah kabur biru redup.
terdon

Jawaban:

14

bagaimana dengan

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

dimana

  • / path / ke / X adalah direktori tujuan Anda
  • Anda mulai dari tempat yang sama ini.
  • kemudian gunakan jawaban lain untuk menghapus direktori kosong.

(di samping catatan ada --junk-pathsopsi di zip, baik saat zip atau unzipping)

Archemar
sumber
7

Saya akan melakukan ini bash, menggunakan globstar. Sebagaimana dijelaskan dalam 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.

Jadi, untuk memindahkan direktori runke direktori tingkat atas x, dan kemudian menghapus sisanya, Anda dapat melakukan:

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

The shoptperintah memungkinkan globstarpilihan. The mv x/**/run/ x/akan memindahkan setiap subdirektori bernama run(catatan bahwa ini hanya bekerja jika hanya ada satu rundirektori) ke xdan findakan menghapus direktori kosong.

Anda bisa melakukan semuanya dalam shell dengan globbing yang panjang, jika Anda mau, tapi saya lebih suka jaring pengaman find -emptyuntuk memastikan tidak ada direktori kosong yang dihapus. Jika Anda tidak peduli tentang itu, Anda dapat menggunakan:

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

Jelas lebih bertele-tele, tetapi melakukan pekerjaan dalam satu langkah:

Dengan asumsi Anda memiliki python diinstal

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

Cara Penggunaan

  1. Salin skrip ke file kosong, simpan sebagai get_folder.py
  2. Jalankan dengan direktori root (containg barang unzipped Anda) dan nama folder untuk "angkat" sebagai argumen:

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

Dan itu dilakukan:

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

Yakub Vlijm
sumber
Ini adalah solusi yang sangat menarik tetapi saya lebih suka tidak menggunakan skrip python karena berbagai alasan. Terima kasih tho!
Idos
Tidak masalah. Mungkin itu berguna bagi orang lain. Ingin tahu mengapa? Saya cukup yakin banyak aplikasi sudah menggunakan python.
Jacob Vlijm
Terutama karena menempatkan file .py di mana saja akan bermasalah karena saya harus menganggap itu di tempat yang sama untuk setiap mesin linux yang akan menjalankan skrip saya (dan skrip saya dijalankan di banyak platform).
Idos
@Idos hanya ingin tahu, platform apa? Python cukup luas. Saya tidak berpikir itu diinstal pada Mac OS X secara default, tetapi sebagian besar distribusi Linux memilikinya
Sergiy Kolodyazhnyy
4

Solusi 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");

Cara kerjanya sederhana: find()subrutin akan melintasi pohon direktori yang diberikan secara rekursif, menemukan direktori yang namanya rundan mendorongnya ke array nama file yang diinginkan. Dalam hal ini, kita mengasumsikan hanya ada satu file dalam daftar, sehingga setelah perintah selesai, kita menggunakan dirmove()dari File::Copy::Recursivemodul, dan memindahkannya ke direktori kerja saat ini dari mana skrip dipanggil. Jadi dalam kasus Anda, Anda akan memanggilnya dari direktori induk ke x.

Pohon direktori asli:

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

Hasil:

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