再帰ディレクトリから特定の名前のフォルダーを抽出し、他のフォルダーを削除する方法は?


10

私は、zipファイルを解凍して得られる次の種類のディレクトリツリーを持っています。

X - > Y - > Z - > 実行 - HERE>ファイルとディレクトリ

したがって、4つのディレクトリがあり、そのうち3つにはファイル(x、y、z)がなく、1つのサブディレクトリしか含まれていません。また、「run」という名前の、興味のあるディレクトリがあります。

「run」ディレクトリ自体(その中のすべてを含む)を、解凍した「ルート」の場所(つまり、「x」はあるが「x」内ではない場所)に移動したい。

仮定:「run」という名前のフォルダーが存在します、そこに到達するために「cd」する必要のあるディレクトリの数はわかりません(3(x、y、z)である可能性があります)。も不明であり、x、y、zなどである必要はありません)。

どうすればこれを達成できますか?私はこの質問の多くのバリエーションを試しましたが、すべて失敗しました。


1
絵がはっきりしないのではないかと思います。テキストのスクリーンショットを投稿しないでください。代わりに、テキストを質問に直接貼り付け、フォーマットツールを使用してください。私はあなたの写真のディレクトリ名さえ読むことができません。私が見るのは薄暗い青いぼかしだけです。
terdon

回答:


14

どうですか

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

どこ

  • / path / to / Xは宛先ディレクトリーです
  • あなたはこれと同じ場所から始めます。
  • 次に、他の回答を使用して空のディレクトリを削除します。

(補足として--junk-paths、zipまたはunzipするときに、zipのオプションがあります)


7

私はこれを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)をに移動xし、find空のディレクトリを削除します。

シェル内で拡張グロビングを使用してすべてを実行することもできますが、find -empty空でないディレクトリが削除されないようにするための安全策が必要です。あなたがそれを気にしないなら、あなたは使うことができます:

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

6

間違いなくもっと冗長ですが、1つのステップでジョブを実行します。

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
    

そしてそれが行われます:

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

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


これは非常に興味深い解決策ですが、私はさまざまな理由でPythonスクリプトを使用しないことを好みます。ありがとうtho!
Idos 2017年

問題ない。たぶん、それは他の誰にも役立つでしょう。なんでなの?多くのアプリケーションがすでにpythonを使用していると確信しています。
Jacob Vlijm 2017年

スクリプトを実行するすべてのLinuxマシンで同じ場所にあると想定する必要があるため、主に.pyファイルを任意の場所に配置すると問題が発生するためです(また、スクリプトは多くのプラットフォームで実行されます)。
Idos 2017年

@Idosは好奇心旺盛で、どのプラットフォームですか?Pythonは非常に普及しています。Mac OS Xにはデフォルトでインストールされているとは思いませんが、ほとんどのLinuxディストリビューションにはインストールされています
Sergiy Kolodyazhnyy

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()from File::Copy::Recursiveモジュールを使用して、スクリプトが呼び出された現在の作業ディレクトリに移動します。したがって、あなたのケースでは、親ディレクトリからに呼び出しますx

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

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

結果:

$ ~/find_dir.pl .  
$ tree 
.
├── levelone
│   └── leveltwo
│       └── levelthree
└── run
    ├── file1
    ├── file2
    └── file3
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.