如何从递归目录中提取特定命名的文件夹,并删除其他文件夹?

如何从递归目录中提取特定命名的文件夹,并删除其他文件夹?

我有这样的目录树,是通过解压缩 zip 文件获得的:

x -> y -> z ->跑步-> 这里是文件和目录

所以有4个目录,其中3个是空的文件(x,y,z)并且只包含1个子目录,并且有一个我感兴趣的目录,名为“跑步”。

我想将“run”目录本身(包括其中的所有内容)移动到我解压缩的“root”位置(即“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 是您的目标目录
  • 你从同一个地方开始。
  • 然后使用其他答案删除空目录。

(顺便说一句--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(请注意,这只在只有一个run目录时才有效)移动到,xfind删除所有空目录。

如果您愿意,您可以使用扩展的通配符在 shell 中完成整个操作,但我更喜欢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. 使用根目录(包含解压的内容)和要“lift”的文件夹名称作为参数运行它:

    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并将其推入所需文件名数组中。在这种情况下,我们假设列表中应该只有一个文件,因此一旦命令完成,我们就使用dirmove()fromFile::Copy::Recursive模块,并将其移动到调用脚本的当前工作目录。因此,在您的情况下,您可以将其从父目录调用到x.

原始目录树:

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

结果:

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

相关内容