Як витягнути конкретно названу папку з рекурсивного каталогу, видалити інші?


10

У мене є таке дерево каталогів, яке отримується після розпакування zip-файлу:

x -> y -> z -> run -> ФАЙЛИ ТА ДИРЕКЦІЇ ТУТ

Отже, є 4 каталоги, 3 з яких порожні від файлів (x, y, z) і містять лише 1 підкаталог, і є каталог, який мене цікавить, під назвою " run ".

Я хочу перенести сам каталог "run" (включаючи все, що знаходиться всередині), до місця "root", де я розпакував (тобто де "x", але не всередині "x").

Припущення: існує папка з назвою "run", але я не знаю, скільки каталогів мені доведеться "cd", щоб дістатися до неї (може бути 3 (x, y, z), може бути 10 і більше. Імена також невідомі і не повинні бути x, y, z тощо).

Як я можу це досягти? Я спробував багато варіантів цього питання, але всі вони зазнали невдачі.


1
Боюся, картина не дуже чітка, ні. Не публікуйте скріншоти тексту . Натомість вставте текст прямо у своє запитання та використовуйте інструменти форматування . Я навіть не можу прочитати ім'я каталогу на вашому малюнку. Я бачу лише тьмяно-синю розмитість.
тердон

Відповіді:


14

а як на рахунок

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

де

  • / шлях / до / X - ваш цільовий каталог
  • ви починаєте з цього ж місця.
  • потім використовуйте іншу відповідь, щоб видалити порожні каталоги.

(на бічній примітці є --junk-pathsопція в 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(зверніть увагу , що це працює тільки , якщо є тільки один runкаталог) , щоб xі findвидалять всі порожні каталоги.

Ви можете зробити все це в оболонці з розширеним глобулом, якщо вам подобається, але я віддаю перевагу безпечній мережі, find -emptyщоб бути впевненою, що не видаляються непорожні каталоги. Якщо вас це не хвилює, ви можете використовувати:

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

6

Виразно більш багатослівний, але виконайте роботу в один крок:

Припустимо, у вас встановлений 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 з різних причин. Дякую тхо!
Ідос

Нема проблем. Можливо, це корисно комусь іншому. Цікаво чому хоч? Я впевнений, що багато програм уже використовують python.
Яків Влійм

В основному, оскільки розміщення файлу .py в будь-якому місці буде проблематичним, тому що я мушу припустити, що він знаходиться в тому ж самому місці для кожної машини Linux, на якій працює мій сценарій (а мій сценарій працює на багатьох платформах).
Ідос

@Idos просто цікаво, які платформи? Пітон досить поширений. Я не думаю, що він встановлений на Mac OS X за замовчуванням, але в більшості дистрибутивів Linux це є
Сергій Колодяжний

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()від File::Copy::Recursiveмодуля, і перемістити його в поточний робочий каталог , з якого викликається скрипт. Таким чином, у вашому випадку ви б назвали це з батьківського каталогу в x.

Оригінальне дерево каталогів:

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

Результат:

$ ~/find_dir.pl .  
$ tree 
.
├── levelone
│   └── leveltwo
│       └── levelthree
└── run
    ├── file1
    ├── file2
    └── file3
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.