C'est probablement très simple, mais je n'arrive pas à comprendre. J'ai une structure de répertoire comme celle-ci (dir2 est à l'intérieur de dir1):
/dir1
/dir2
|
--- file1
|
--- file2
Quel est le meilleur moyen d '' aplatir 'cette structure de directeur de manière à obtenir fichier1 et fichier2 dans dir1 et non dans dir2.
Réponses:
Vous pouvez le faire avec GNU
find
et GNUmv
:En gros, si cela
find
parcourt l’ensemble de l’arborescence de répertoires et que chaque fichier (-type f
) qui ne se trouve pas dans le répertoire de niveau supérieur (-mindepth 2
), il exécute unmv
pour le déplacer dans le répertoire de votre choix (-exec mv … +
). L'-t
argument àmv
vous permet de spécifier le répertoire de destination en premier, ce qui est nécessaire car la+
forme de-exec
met tous les emplacements source à la fin de la commande. Les-i
marquesmv
demandent avant d’écraser les doublons; vous pouvez remplacer-f
pour les écraser sans demander (ou-n
pour ne pas demander ou écraser).Comme le souligne Stephane Chazelas, ce qui précède ne fonctionne qu'avec les outils GNU (standard sur Linux, mais pas sur la plupart des autres systèmes). Ce qui suit est un peu plus lent (car il appelle
mv
plusieurs fois) mais beaucoup plus universel:la source
-exec +
pour qu'il n'exécute pas un grand nombre de processus demv
mv
a besoin de la destination comme argument final, mais + aurait les sources comme argument final. Find n'acceptera même pas la syntaxe que vous avez changée en (find: missing argument to `-exec'
)mv
que-t
nous pouvons l'utiliser, alors je vais le changer pour cela.find
imprime les fichiers cachés (points) par défaut. La profondeur est relative au répertoire que vous passez à trouver.find ./dir -mindepth 2 -type f -exec mv -f '{}' ./dir ';'
cas de doublonsEn zsh:
**/
traverse les sous-répertoires de manière récursive. Le qualificatif glob ne.
correspond qu'aux fichiers normaux etD
garantit que les fichiers point sont inclus (par défaut, les fichiers dont le nom commence par un.
sont exclus des correspondances génériques). Pour nettoyer les répertoires maintenant vides par la suite, exécutezrmdir dir1/**/*(/Dod)
-/
restreint aux répertoires, etod
ordonne d'abord la profondeur des correspondances afin de la supprimerdir1/dir2/dir3
avantdir1/dir2
.Si la longueur totale des noms de fichier est très grande, vous pouvez rencontrer une limitation de la longueur de la ligne de commande. Zsh a builtins pour
mv
etrmdir
qui ne sont pas concernés par cette limitation: courirzmodload zsh/files
pour les activer.Avec uniquement les outils POSIX:
ou (plus rapide car il n'est pas nécessaire d'exécuter un processus séparé pour chaque fichier)
la source
Essayez de faire ceci:
ou pour chaque fichier correspondant
file[0-9]*
dans le sous-répertoire:Voir http://mywiki.wooledge.org/glob
la source
{}
dans mon vrai problème.J'ai écrit deux fonctions que vous pouvez utiliser ensemble pour cela, vous pouvez limiter le niveau de répertoire en ajoutant un
-maxdepth $VAL
paramètre.la source
Développant la réponse populaire à cette question, car j'avais un cas d'utilisation pour aplatir un répertoire contenant des fichiers du même nom.
Dans ce cas, l' option
-i
(--interactive
) passée àmv
ne produirait pas le résultat souhaité pour aplatir la structure de répertoires et gérer les conflits de noms. Donc, il est simplement remplacé par--backup=t
(équivalent à--backup=numbered
). Plus de documentation sur l' option-b
(--backup
) disponible à l' adresse https://www.gnu.org/software/coreutils/manual/coreutils.html#Backup-options .Résultant en:
Quels rendements:
la source
tar et zip ont tous les deux la capacité d’incorporer puis de dépouiller une structure de répertoires, ainsi j’ai pu rapidement aplatir un répertoire imbriqué avec
tar -cvf all.tar *
suivi du déplacement de all.tar vers un nouvel emplacement, puis
tar -xvf all.tar --strip=4
la source