web-dev-qa-db-fra.com

Comment dissoudre tous les sous-dossiers

Existe-t-il une ligne de commande one-liner pour déplacer tout le contenu de tous les sous-dossiers directs d’un dossier dans le dossier lui-même et supprimer les sous-dossiers (qui sont maintenant vides)? C'est-à-dire, éliminer un niveau dans la hiérarchie des dossiers?

Pour être absolument clair, la structure plus profonde du sous-dossier doit être préservée.

Je me suis heurté à cela à quelques reprises maintenant, et j'ai été un peu déçu que cela ne semble pas être une fonctionnalité de Dolphin, ni quelque chose avec lequel d'autres personnes se débattent.

Je suppose que cela devra peut-être être divisé en deux, en déplaçant le contenu des sous-dossiers et en supprimant ceux-ci. Toutefois, cela peut avoir pour effet indésirable de supprimer des sous-dossiers vides de second niveau.

4
oulenz

En fait, pas un vrai one-liner:

find . -mindepth 2 -maxdepth 2 -print -exec mv --backup=numbered -t . '{}' + \
&& find . -mindepth 1 -maxdepth 1 -type d -empty -delete

Recherchez tout d'abord dans le sous-dossier avec la profondeur exacte 2 et déplacez-le vers .. Ensuite, recherchez et supprimez tous les dossiers vides du répertoire actuel.

  • si vous avez des fichiers/dossiers du même nom, ils seront renommés avec original_filename.~n~ (n signifiant 1, 2, 3 ...).
  • Notez que tous les sous-dossiers vides seront supprimés.

Mise à jour:

Je ne suis pas content de la solution ci-dessus. Trop de mises en garde et de problèmes. Par exemple, lorsque --backup = numbered renomme le dossier parent de votre dossier que vous souhaitez déplacer ...

mkdir -p test/test
mv test/test . --backup=numbered
mv: cannot move 'test/test' to './test': No such file or directory

Mieux vaut utiliser un répertoire temporaire pour éviter les problèmes. Le répertoire temporaire doit se trouver sur le même système de fichiers pour éviter de copier les fichiers.

tmpdir=$(mktemp -d)
find . -mindepth 2 -maxdepth 2 -print -exec mv -b -t $tmpdir '{}' +
find . -mindepth 1 -maxdepth 1 -type d -empty -delete
mv -b $tmpdir/* .
rm $tmpdir
5
pLumo

Pour vous protéger contre la suppression de sous-répertoires vides, le moyen le plus simple d’IMO consiste à accéder à un répertoire temporaire, puis à le renommer. Disons que le répertoire en question est foo et que vous voulez que foo/*/* devienne foo/*. Faites quelque chose comme:

tar c --remove-files foo | tar xv --strip-components=2 --backup=t --one-top-level=temp
mv temp foo
  • Avec --remove-files, le premier tar supprimera les fichiers au fur et à mesure de son traitement, supprimant finalement foo lui-même.
  • Avec --strip-components=2, le second tar coupera le foo/*/ des chemins extraits, de sorte que foo/a/b deviendra b.
  • --backup=t est identique à cp ou mv - crée des copies de sauvegarde numérotées. Cependant, mv crée des copies des répertoires s'ils portent le même nom, mais tar fusionnera les répertoires et effectuera des sauvegardes de fichiers.
  • --one-top-level=temp indique à tar de créer un répertoire nommé temp et d'extraire des fichiers à cet emplacement.

Par exemple:

$ tree bar
bar
├── a
│   ├── c
│   │   └── bar
│   ├── d
│   │   └── bar
│   ├── e
│   │   └── bar
│   └── f
│       └── bar
├── b
│   ├── c
│   │   └── bar
│   ├── d
│   │   └── bar
│   ├── e
│   │   └── bar
│   └── f
│       └── bar
└── c
    ├── c
    │   └── bar
    ├── d
    │   └── bar
    ├── e
    │   └── bar
    └── f
        └── bar

Et après avoir exécuté les commandes tar:

$ tar c --remove-files bar | tar xv --strip-components=2 --backup=t --one-top-level=temp
bar/a/e/
bar/a/e/bar
bar/a/f/
bar/a/f/bar
bar/a/c/
bar/a/c/bar
bar/a/d/
bar/a/d/bar
bar/b/e/
bar/b/e/bar
Renaming ‘temp/e/bar’ to ‘temp/e/bar.~1~’
bar/b/f/
bar/b/f/bar
Renaming ‘temp/f/bar’ to ‘temp/f/bar.~1~’
bar/b/c/
bar/b/c/bar
Renaming ‘temp/c/bar’ to ‘temp/c/bar.~1~’
bar/b/d/
bar/b/d/bar
Renaming ‘temp/d/bar’ to ‘temp/d/bar.~1~’
bar/c/e/
bar/c/e/bar
Renaming ‘temp/e/bar’ to ‘temp/e/bar.~2~’
bar/c/f/
bar/c/f/bar
Renaming ‘temp/f/bar’ to ‘temp/f/bar.~2~’
bar/c/c/
bar/c/c/bar
Renaming ‘temp/c/bar’ to ‘temp/c/bar.~2~’
bar/c/d/
bar/c/d/bar
Renaming ‘temp/d/bar’ to ‘temp/d/bar.~2~’

$ tree temp
temp
├── c
│   ├── bar
│   ├── bar.~1~
│   └── bar.~2~
├── d
│   ├── bar
│   ├── bar.~1~
│   └── bar.~2~
├── e
│   ├── bar
│   ├── bar.~1~
│   └── bar.~2~
└── f
    ├── bar
    ├── bar.~1~
    └── bar.~2~

4 directories, 12 files

Avec la sortie tar, vous pouvez voir quand tar renommer des fichiers à sauvegarder, ce qui vous permet de savoir quels fichiers sont devenus quelles sauvegardes.


Je suis légèrement surpris que cela fonctionne, mais vous pouvez en fait donner le même nom de répertoire pour --one-top-level et éviter ainsi de devoir le renommer. Juste ce pipeline est suffisant:

tar c --remove-files bar | tar xv --strip-components=2 --backup=t --one-top-level=bar
1
muru