Объединить 2 дерева каталогов в Linux без копирования?

Самый легкий способ сделать это на Linux - то, при резервировании блока наверху или нижнего диапазона стандартного эфемерного диапазона портов.

Узнайте то, что Ваш текущий диапазон путем выполнения

cat /proc/sys/net/ipv4/ip_local_port_range

Затем установите его путем повторения чего-то другого в него (и изменения sysctl.conf или подобный, чтобы заставить его произойти на начальной загрузке также). Моя система использует 32768-61000, таким образом, я мог изменить это на 32768-60000 в сочетании с SELinux/AppArmor для резервирования 60001-61000 для моего приложения.

echo "32768 60000" > /proc/sys/net/ipv4/ip_local_port_range

Я не знаю о способе вырезать разрыв посреди эфемерного диапазона.

35
задан 18 March 2015 в 19:15
6 ответов
rsync -ax --link-dest=dir1/ dir1/ merged/
rsync -ax --link-dest=dir2/ dir2/ merged/

Это создало бы hardlinks вместо того, чтобы переместить их, можно проверить, что они были перемещены правильно, затем, удалить dir1/ и dir2/.

28
ответ дан 28 November 2019 в 19:51
  • 1
    Один протест: сделайте --link-dest абсолютный путь, или относительно merged/; или это скопирует. –  Tobu 4 July 2010 в 00:19

Можно использовать, переименовывают (иначе предварительное имя, от пакета жемчуга) для этого. Остерегайтесь этого, имя не обязательно относится к команде, которую я описываю за пределами debian/ubuntu (хотя это - единственный портативный файл жемчуга при необходимости в нем).

mv -T dir1 merged
rename 's:^dir2/:merged/:' dir2/* dir2/*/*
find dir2 -maxdepth 1 -type d -empty -delete

У Вас также есть опция использования vidir (от moreutils), и редактирование путей к файлам из Вашего предпочтительного текстового редактора.

5
ответ дан 28 November 2019 в 19:51

Я люблю rsync и предварительно называю решения, но если Вы действительно хотите заставить mv сделать работу и

  • Ваша находка знает -print0 и -depth,
  • Ваш xargs знает -0,
  • у Вас есть printf,

затем возможно обработать большое количество файлов, которые могли бы иметь случайный пробел на их имена, все со сценарием оболочки стиля Границы:

#!/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
3
ответ дан 28 November 2019 в 19:51

Грубая сила bash

#! /bin/bash

for f in $(find dir2 -type f)
do
  old=$(dirname $f)
  new=dir1${old##dir2}
  [ -e $new ] || mkdir $new
  mv $f $new
done

тест делает это

# setup 
for d in dir1/{a,b,c} dir2/{a,b,c,d} ; do mkdir -p $d ;done
touch dir1/a/file{1,2} dir1/b/file{3,4} dir2/a/file{5,6} dir2/b/file{7,8} dir2/c/file{9,10} dir2/d/file11

# do it and look
$ find dir{1,2} -type f
dir1/a/file1
dir1/a/file2
dir1/a/file5
dir1/a/file6
dir1/b/file3
dir1/b/file7
dir1/b/file8
dir1/c/file4
dir1/c/file9
dir1/c/file10
dir1/d/file11
2
ответ дан 28 November 2019 в 19:51

Я должен был несколько раз делать это для деревьев исходного кода на различных стадиях развития. Мое решение состояло в том, чтобы использовать Мерзавца следующим образом:

  1. Создайте репозиторий мерзавца и добавьте все файлы от dir1.
  2. Фиксация
  3. Удалите все файлы и копию в файлах от dir2
  4. Фиксация
  5. Различия в представлении между двумя точками фиксации и принимают тщательные решения относительно того, как я хочу объединить результаты.

Можно ловко обойти его с ветвлением и т.д, но это - общее представление. И у Вас есть меньше страха о наполнении его, потому что у Вас есть полный снимок каждого состояния.

0
ответ дан 28 November 2019 в 19:51

Странно, что никто не заметил, что cp имеет параметр -l :

-l, --link
       hard link files instead of copying

Вы можете сделать что-то вроде

% mkdir merge
% cp -rl dir1/* dir2/* merge
% rm -r dir*
% tree merge 
merge
├── a
│   ├── file1.txt
│   ├── file2.txt
│   ├── file5.txt
│   └── file6.txt
├── b
│   ├── file3.txt
│   ├── file7.txt
│   └── file8.txt
└── c
    ├── file10.txt
    ├── file4.txt
    └── file9.txt

13 directories, 0 files
21
ответ дан 28 November 2019 в 19:51

Теги

Похожие вопросы