再帰ディレクトリから特定の名前のフォルダを抽出し、他のフォルダを削除するにはどうすればよいですか?

再帰ディレクトリから特定の名前のフォルダを抽出し、他のフォルダを削除するにはどうすればよいですか?

zipファイルを解凍した次のディレクトリツリーがあります。

x -> y -> z ->走る-> ファイルとディレクトリは次のとおりです。

したがって、4つのディレクトリがあります。そのうちの3つは空のファイル(x、y、z)で、サブディレクトリは1つだけ含まれています。そして私が興味を持っているディレクトリは」走る」。

「実行」ディレクトリ自体(その中のすべての項目を含む)を解凍した「ルート」の場所(たとえば「x」はありますが、「x」の内部ではない)に移動したいと思います。

仮定:はい存在する"run"というフォルダがありますが、フォルダに到達するために "cd"する必要があるディレクトリの数はわかりません(おそらく3(x、y、z)、たぶん10個以上)。名前も不明で、フォルダには含まれません。 x、y、zなどである必要はありません。)

どうすればいいですか?様々なバリエーションを試しましたこの問題しかし、彼らはすべて失敗しました。

答え1

何について

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

どこ

  • /path/to/X はターゲットディレクトリです。
  • 同じ場所から始めます。
  • 次に、別の答えを使用して空のディレクトリを削除します。

(BTW --junk-paths、圧縮または解凍時にzipオプションがあります)

答え2

私はbashこれをしたglobstar。説明したように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.

したがって、ディレクトリをrun最上位レベルに移動してx残りを削除するには、次の手順を実行します。

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

このshoptコマンドを使用すると、このglobstarオプションが有効になります。mv x/**/run/ x/指定されたすべてのサブディレクトリrun(ディレクトリが1つしかない場合にのみ機能します)がrun移動され、空のディレクトリxfind削除されます。

必要に応じて、拡張ワイルドカードを使用してシェルですべての操作を実行できますが、find -empty空でないディレクトリが削除されないようにするセーフティネットをお勧めします。これについて気にしない場合は、次のものを使用できます。

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

答え3

確かにより詳細ですが、作業は一歩で完了します。

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]))

使い方

  1. スクリプトを空のファイルにコピーして別の名前で保存します。get_folder.py
  2. ルートディレクトリ(解凍されたコンテンツを含む)と「リフト」したいフォルダ名を引数として実行します。

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

それだけです:

ここに画像の説明を入力してください。

ここに画像の説明を入力してください。

答え4

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

仕組みは簡単です。find()サブルーチンは指定されたディレクトリツリーを再帰的に移動し、名前付きディレクトリを見つけて必要なファイル名の配列runにプッシュします。この場合、リストにはファイルが1つだけ存在する必要があると仮定するため、コマンドが完了したらdirmove()fromFile::Copy::Recursiveモジュールを使用して呼び出しスクリプトの現在の作業ディレクトリに移動します。したがって、あなたの場合は、親ディレクトリからx

元のディレクトリツリー:

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

結果:

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

関連情報