J'ai deux arbres de répertoire avec des mises en page similaires, c'est-à-dire.
.
|-- dir1
| |-- a
| | |-- file1.txt
| | `-- file2.txt
| |-- b
| | `-- file3.txt
| `-- c
| `-- file4.txt
`-- dir2
|-- a
| |-- file5.txt
| `-- file6.txt
|-- b
| |-- file7.txt
| `-- file8.txt
`-- c
|-- file10.txt
`-- file9.txt
Je voudrais fusionner les arbres de répertoire Dir1 et Dir2 pour créer:
merged/
|-- a
| |-- file1.txt
| |-- file2.txt
| |-- file5.txt
| `-- file6.txt
|-- b
| |-- file3.txt
| |-- file7.txt
| `-- file8.txt
`-- c
|-- file10.txt
|-- file4.txt
`-- file9.txt
Je sais que je peux faire cela à l'aide de la commande "CP", mais je veux déplacer les fichiers au lieu de copier, car les répertoires réels que je veux fusionner sont vraiment volumineux et contiennent de nombreux fichiers (des millions). Si j'utilise "MV", je reçois le "fichier existant" une erreur en raison de noms de répertoires contradictoires.
Mise à jour: Vous pouvez supposer qu'il n'y a aucun fichier en double entre les deux arbres de répertoire.
rsync -ax --link-dest=dir1/ dir1/ merged/
rsync -ax --link-dest=dir2/ dir2/ merged/
Cela créerait des hardlinks plutôt que de les déplacer, vous pouvez vérifier qu'ils ont été déplacés correctement, puis, enlever dir1/
et dir2/
.
C'est étrange personne noté que cp
a option -l
:
- L, - Link [.____] Les fichiers de liaison durs au lieu de copier
Vous pouvez faire quelque chose comme
[.____]% Mkdir fusionnez [.____]% cp -rl Dir1/* dir2/* fusionner [.____]% RM -r dir " Fusionner [.____] .____.] ├── a │ ├── file1.txt ││── file2.txt [.____] │ ├── file5.txt [.____] └── file6.txt [.____] ├── B [.____] ││── file3.txt [.____] ││── file7.txt8. txt └── c [.____] ├── file10.txt ├── file4.txt └── file9.txt 13 répertoires, 0 fichiers [.____]
Vous pouvez utiliser Rename (AKA PRENAME, du paquet PERL) pour cela. Méfiez-vous que le nom ne fait pas nécessairement référence à la commande que je décris en dehors de Debian/Ubuntu (bien que ce soit un fichier PERL portable unique si vous en avez besoin).
mv -T dir1 merged
rename 's:^dir2/:merged/:' dir2/* dir2/*/*
find dir2 -maxdepth 1 -type d -empty -delete
Vous avez également la possibilité d'utiliser Vidir (à partir de plus) et d'éditer les chemins de fichiers à partir de votre éditeur de texte préféré.
J'aime le rsync et préname Solutions, mais si vous voulez vraiment faire MV faire le travail et
-print0
et -depth
,-0
,ensuite, il est possible de gérer un grand nombre de fichiers pouvant avoir des espaces aléatoires dans leurs noms, tous avec un script shell de style Bourne:
#!/bin/sh
die() {
printf '%s: %s\n' "${0##*/}" "$*"
exit 127
}
maybe=''
maybe() {
if test -z "$maybe"; then
"$@"
else
printf '%s\n' "$*"
fi
}
case "$1" in
-h|--help)
printf "usage: %s [-n] merge-dir src-dir [src-dir [...]]\n" "${0##*/}"
printf "\n Merge the <src-dir> trees into <merge-dir>.\n"
exit 127
;;
-n|--dry-run)
maybe=NotRightNow,Thanks.; shift
;;
esac
test "$#" -lt 2 && die 'not enough arguments'
mergeDir="$1"; shift
if ! test -e "$mergeDir"; then
maybe mv "$1" "$mergeDir"
shift
else
if ! test -d "$mergeDir"; then
die "not a directory: $mergeDir"
fi
fi
xtrace=''
case "$-" in *x*) xtrace=yes; esac
for srcDir; do
(cd "$srcDir" && find . -print0) |
xargs -0 sh -c '
maybe() {
if test -z "$maybe"; then
"$@"
else
printf "%s\n" "$*"
fi
}
xtrace="$1"; shift
maybe="$1"; shift
mergeDir="$1"; shift
srcDir="$1"; shift
test -n "$xtrace" && set -x
for entry; do
if test -d "$srcDir/$entry"; then
maybe false >/dev/null && continue
test -d "$mergeDir/$entry" || mkdir -p "$mergeDir/$entry"
continue
else
maybe mv "$srcDir/$entry" "$mergeDir/$entry"
fi
done
' - "$xtrace" "$maybe" "$mergeDir" "$srcDir"
maybe false >/dev/null ||
find "$srcDir" -depth -type d -print0 | xargs -0 rmdir
done
J'ai dû faire cela plusieurs fois pour les arbres de code source à différentes étapes de développement. Ma solution était d'utiliser GIT de la manière suivante:
Vous pouvez la définir avec ramification et ainsi de suite, mais c'est l'idée générale. Et vous avez moins peur de la farcir parce que vous avez un instantané complet de chaque état.