Мое злое дополнение к fstab приводило только к чтению также [везде]... Нашел это решение; Загрузитесь с (предыдущей версии не имеет значения )установочный компакт-диск или флешка сервера, выберите «Восстановить сломанную систему» (, язык, клавиатуру )и вставьте известное имя сервера и выберите «Устройство для использования в качестве корневая файловая система" [;/dev/sda1]. Выберите «Выполнить оболочку в /dev/sda1» и в нижней части экрана вы найдете #.... с #cd /etc Мне было разрешено редактировать fstab (вычисление «зла» ).... выйти и перезагрузиться.
на самом деле это две команды. во-первых, это mv
файлы на один уровень выше, во-вторых, это удаление пустых каталогов.
(обе команды объединены с &&
, чтобы они выглядели как один -лайнер)
find -H PARENT -mindepth 3 ! -type d -execdir cp --backup=numbered -al {}.. \; -delete && find -H PARENT -depth -mindepth 2 -type d -exec rmdir {} +
вместо mv
создайте жесткие ссылки и удалите источник. cp
предоставляет сборку -в решении для резервного копирования :
cp --backup=numbered
автоматически переименует файл, если другой файл уже существует
cp -l
создать жесткую ссылку вместо копирования
cp -a
сохранить метаданные (mtime, разрешения)
find -delete
удаляет все рекурсивно (использовать с осторожностью)
все find
аргументы объяснены:
найти -H
в случае, если PARENT является символической ссылкой
найти ! -type d
то же, что и-type f
(!
= инвертировать аргумент)
найти -mindepth 3
только */ */ */файлы 3-го уровня (использовать -maxdepth 3
для большей безопасности)
найти -execdir
запустить команду из подкаталога
объяснение разницы между \;
и +
:
найти -exec CMD {} \;
серийный номер 1 :1 выполнение команды CMD ARG1; CMD ARG2;... (где ARG — результат find)
найти -exec CMD {} +
параллельное выполнение CMD ARG1 ARG2 ARG3... ARGN;
вместо запуска из терминала вы можете заменить PARENT
на "$@"
и создать небольшой сценарий оболочки, который будет работать с несколькими аргументами.
sh./myscript.sh PARENT [PARENT2...]
запустить скрипт
#!/bin/sh
test -e "$1" || exit 1
find -H "$@" -mindepth 3 ! -type d -execdir cp --backup=numbered -al {}.. \; -delete
find -H "$@" -depth -mindepth 2 -type d -exec rmdir {} +
Это можно легко решить с помощью простого сценария bash, чтобы сэкономить время, если у вас много каталогов для этого.
Только с одним каталогом:
parent/
└── DIRA
└── DIR1
├── file1.ogg
├── file2.ogg
└── file3.ogg
Затем внутри DIR1:
# You can also use ; over && but the second one is more reliable,
# specially if you are doing this in a remote server.
mv *.ogg../ && cd../ && rmdir DIR1/
Результат:
parent/
└── DIRA
├── file1.ogg
├── file2.ogg
└── file3.ogg
Если вы уверены, что все файлы внутри каталога второго уровня имеют расширение.ogg, вы можете использовать mv*вместо mv *.ogg .
Поскольку почти все дистрибутивы Linux --, по крайней мере основные --, поставляются с предустановленным Python -, вероятно, было бы проще вместо этого просто написать простой скрипт Python.
#!/usr/bin/env python3
import sys
from pathlib import Path
def flatten_and_del(targdir):
pardir = targdir.parent
for f in targdir.glob("*"):
f.rename(pardir / f.name)
targdir.rmdir()
def process_dir(parent):
parent = Path(parent)
if not parent.is_dir():
raise RuntimeError(f"{parent} is not a directory!")
for f in parent.glob("*"):
if not f.is_dir():
continue
flatten_and_del(f)
if __name__ == "__main__":
process_dir(sys.argv[1])
Сохраните его как, скажем, tidy-dirs.py
и запустите так:
python3 tidy-dirs.py path/to/PARENT
ВНИМАНИЕ:Как отметил αғsнιη в своем комментарии, этот метод приведет к потере данных, если имя файла конфликтует. Если вы не хотите, чтобы это произошло, в flatten_and_del
добавьте проверку target.exists()
перед выполнением.rename()
Сzsh
:
autoload zmv # best in ~/.zshrc
zmv '(PARENT)/(*)/*/(*)(#qD)' '$1/$2/$3'
rmdir PARENT/*/*(#qD/^F)