Özel olarak adlandırılmış bir klasörü özyinelemeli bir dizinden ayıklamak, diğerlerini silmek nasıl?


10

Bir zip dosyasını unzipping elde edilen dizin ağacı bu tür var:

x -> y -> z -> koşmak -> BURADA DOSYALAR VE DİREKTÖRLER

Bu nedenle, 3 tanesi dosyalardan (x, y, z) boş ve yalnızca 1 alt dizin içeren 4 dizin vardır ve ilgilendiğim, " run " adlı dizin var .

"Çalıştır" dizini kendisini (içinde her şey dahil) sıkıştırılmış "kök" konuma taşımak istiyorum (yani "x" olduğu, ancak "x" içinde değil).

Varsayımlar: "Çalıştır" adında bir klasör var , ancak ona ulaşmak için "cd" ye kaç dizin eklemem gerektiğini bilmiyorum (3 (x, y, z) olabilir, 10 veya daha fazla olabilir. ayrıca bilinmemektedir ve x, y, z vb. olması gerekmez).

Bunu nasıl başarabilirim? Bu sorunun birçok varyasyonunu denedim ama hepsi başarısız oldu.


1
Korkarım resim çok net değil, hayır. Lütfen metnin ekran görüntülerini göndermeyin . Bunun yerine metni doğrudan sorunuza yapıştırın ve biçimlendirme araçlarını kullanın . Resminizdeki dizin adını bile okuyamıyorum. Tek gördüğüm loş mavi bir bulanıklık.
terdon

Yanıtlar:


14

ne dersin

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

nerede

  • / path / to / X, hedef dizininizdir
  • aynı yerden başlıyorsunuz.
  • sonra boş dizinleri kaldırmak için başka bir cevap kullanın.

(bir yan notta --junk-paths, zipleme veya açma sırasında zip'te bir seçenek vardır )


7

Bunu bashkullanarak yapardım globstar. Açıklandığı gibi 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.

Bu nedenle, dizini runüst düzey dizine taşımak xve geri kalanını silmek için şunları yapabilirsiniz:

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

shoptKomut sağlayan globstarseçeneği. mv x/**/run/ x/Adlı tüm alt dizinleri hareket edecek run(sadece bir tane varsa bu sadece çalıştığını not runetmek dizin) xve findherhangi bir boş dizinleri siler.

İsterseniz her şeyi genişletilmiş globbing ile yapabilirsiniz, ancak find -emptyboş olmayan dizinlerin silinmediğinden emin olmak için güvenlik ağını tercih ederim . Bunu önemsemiyorsanız şunları kullanabilirsiniz:

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

6

Kesinlikle daha ayrıntılı, ancak işi bir adımda yapmak:

Yüklü python olduğunu varsayarsak

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

Nasıl kullanılır

  1. Komut dosyasını boş bir dosyaya kopyalayın, get_folder.py
  2. Kök dizini (sıkıştırılmamış öğelerinizi barındıran) ve bağımsız değişken olarak "kaldırılacak" klasörün adını kullanarak çalıştırın:

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

Ve yapılır:

resim açıklamasını buraya girin

resim açıklamasını buraya girin


Bu çok ilginç bir çözüm ama çeşitli nedenlerle herhangi bir python betiği kullanmamayı tercih ediyorum. Teşekkürler tho!
Idos

Sorun değil. Belki de başkası için faydalıdır. Neden olsa merak mı ediyorsunuz? Birçok uygulamanın zaten python kullandığından eminim.
Jacob Vlijm

Temelde .py dosyasını herhangi bir yere yerleştirmek, betiğimi çalıştıracak (ve betiğim birçok platformda çalıştırılır) her linux makinesi için aynı yerde olduğunu varsaymak zorunda olduğum için sorunlu olacaktır.
Idos

@Idos sadece merak ediyor, hangi platformlar? Python oldukça yaygın. Mac OS X'e varsayılan olarak yüklendiğini sanmıyorum, ancak çoğu Linux dağıtımında var
Sergiy Kolodyazhnyy

4

Perl çözeltisi

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

Bunun çalışma şekli basittir: find()altyordam, verilen dizin ağacını özyinelemeli olarak gezer, adı olan dizini bulur ve runistenen dosya adları dizisine iter. Bu durumda, biz böylece komut tamamlanıncaya kez, kullandığımız, listedeki sadece bir dosya olmalıdır varsayalım dirmove()gelen File::Copy::Recursivemodül ve komut dosyası çağrıldığı geçerli çalışma dizinine taşıyın. Böylece sizin durumunuzda üst dizinden 'e çağırırsınız x.

Orijinal dizin ağacı:

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

Sonuç:

$ ~/find_dir.pl .  
$ tree 
.
├── levelone
│   └── leveltwo
│       └── levelthree
└── run
    ├── file1
    ├── file2
    └── file3
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.