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
移動され、空のディレクトリx
がfind
削除されます。
必要に応じて、拡張ワイルドカードを使用してシェルですべての操作を実行できますが、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]))
使い方
- スクリプトを空のファイルにコピーして別の名前で保存します。
get_folder.py
ルートディレクトリ(解凍されたコンテンツを含む)と「リフト」したいフォルダ名を引数として実行します。
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