Рекурсивная утилита перемещения на Unix?

Сервер Офисных коммуникаций не мог бы быть настолько дорогим. Если Ваша компания лицензировала Версию для предприятия Office, она уже идет с Лицензией на клиентский доступ для Коммуникатора.

Это делает цену OCS только 700$ (для сервера), даже если у Вас есть тысячи клиентов.

Пища для размышления.

6
задан 12 June 2009 в 12:46
11 ответов

На mv (1) страница справочника от гну mv:

-u, --update move only when the SOURCE file is newer than the destination file or when the destination file is missing

2
ответ дан 3 December 2019 в 00:27
  • 1
    Вы уверены, что это работает? Например; [thomas@ana ~] $ mkdir-p a/b [thomas@ana ~] $ касаются a/b/c1 [thomas@ana ~], $ rsync-arv a2, отправляющий отправленные 125 байтов созданного каталога a2 a/a/b/a/b/c1 возрастающего списка файлов, получил 39-байтовый 328,00 байтов/секунда общий размер, 0 ускорений, 0.00 [thomas@ana ~], $ касаются a/b/c2 [thomas@ana ~] $ mv-u /* a2 mv: не может переместиться a/b' to a2/b': Каталог, не пустой [thomas@ana ~] $ mv-u-T a2 mv: не может переместиться a' to a2': Каталог, не пустой –  Thomas Vander Stichele 12 June 2009 в 12:42

предложенный mv -uf dir1/* dir2/ переместите (sub) каталоги, не каждый файл. Вы могли бы попытаться использовать find

cd dir1
find . -type d -exec mkdir -p dir2/"{}" \;
find . -type f -exec mv -uf "{}" dir2/"{}" \;

или что-то подобное

2
ответ дан 3 December 2019 в 00:27

Не делает

mv -uf tree1/* tree2/

работа?

1
ответ дан 3 December 2019 в 00:27
  • 1
    Нет: thomas@ana ~] $ mv-uf /* a2/mv: не может переместиться a/b' to a2/b': Каталог, не пустой –  Thomas Vander Stichele 12 June 2009 в 12:47

Полуночный Командующий (мГц) также хорош для этого вида материала. Файлы тега с CTRL-t, нажмите F6, и когда он просит перезаписывать целевые файлы, выбирать Update, если Вы хотите перезаписать более старые файлы.

1
ответ дан 3 December 2019 в 00:27

допустить ошибку

mv dir1/* dir2/

или просто

rsync -arv --remove-source-files  tree1/* tree2

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

find sourcedir -maxdepth 1 -exec echo mv {} targetdir/ \;

должны быть хорошие опции

find sourcedir -maxdepth 1 -print0 |xargs -0 -I _ echo mv _ targetdir
find sourcedir -maxdepth1 -exec mv {} targetdir/ +

оба не действительно необходимы, потому что mv просто выбирает 2 варианта (исходная цель), таким образом, необходимо будет жить со множеством процессов в этом случае.

0
ответ дан 3 December 2019 в 00:27
  • 1
    Это не что I' m просьба о. Ваше решение идет только один уровень глубоко и doesn' t рекурсивно вызывают в подкаталоги. –  Thomas Vander Stichele 12 June 2009 в 12:48
  • 2
    Это doesn' t рекурсивно вызывают, потому что с последующим mv управляют it' s не необходимый для рекурсивного вызова дальше, чем один каталог. Однако, так как Вы запустили с rsync, который я рекомендую моему - переключатель удалять-исходных-файлов, который сохранит Вас с инструментом, Вы знаете плюс он won' t используют столько же пространства сколько rsync/rm комбинация. –  serverhorror 12 June 2009 в 13:02
  • 3
    На другой ноте: так как я просто читал Ваше сообщение снова относительно слияния, Вы могли бы хотеть играть с-n или-i опциями от mv –  serverhorror 12 June 2009 в 13:03
  • 4
    I' m вполне уверенный you' ре, не рассматривая того, что большая часть дерева уже существует в месте назначения, таким образом, Ваша первая команда mv не будет работать. Не уверенный, чему-n или-i помогут здесь. Попробуйте пример. –  Thomas Vander Stichele 13 June 2009 в 10:41
cd /tree1
mv * /tree2 

Это не переместит скрытые файлы или папки, но Ваш исходный пример не был бы также.

0
ответ дан 3 December 2019 в 00:27

переключитесь на каталог, который Вы хотите переместить и сделать

tar cf - * | ( cd /target; tar xfp -)

Более быстрый, чем mv...

-1
ответ дан 3 December 2019 в 00:27
  • 1
    Вы имели в виду более быстрый, чем право CP? –  rkthkr 11 June 2009 в 17:16
  • 2
    Более быстрый mv только , если источник и цель находится в различных файловых системах. –  MikeyB 11 June 2009 в 21:05
  • 3
    Этот doesn' t перемещают inodes вообще. –  Thomas Vander Stichele 12 June 2009 в 12:50

Вы можете использовать "cp -l & rm" для перемещения внутри устройства:

cp -alv --backup=numbered tree1/* tree2 &&
rm -rf tree1/
  • -l of cp , чтобы использовать жесткие ссылки вместо копирования, (это также предотвращает операции между устройствами)
  • - backup = numbered из cp для резервного копирования существующих файлов в целевом каталоге

И будьте осторожны с этими двумя проблемами:

  • используйте && , чтобы предотвратить удаление ваших нескопированных данных, если вы случайно запустите их на разных устройствах. (в случае corss-device cp завершается со статусом « 1 », по крайней мере для GNU coreutils)
  • файлы, начинающиеся с «. » в tree1 , вы потеряете их, если они есть.
1
ответ дан 3 December 2019 в 00:27

Ответ Хавьера с поиском работает хорошо, за исключением того, что он не удаляет исходные каталоги. Добавьте в конце:

rmdir $(find . -type d  |grep -v ^\.$)
1
ответ дан 3 December 2019 в 00:27

Я думаю, что mv не делает то, что вы думаете.

Файловая система unix состоит из 3 компонентов:

  • записей каталога
  • inodes
  • блоков

A запись в каталоге указывает на индексный дескриптор.

В индексном дескрипторе есть метатаданные о файле (это файл, каталог, именованный канал? Кто им владеет? Какие разрешения? Какие блоки использует этот индексный дескриптор?

Блоки - это вещи, которые фактически содержат содержимое файла.

Итак - когда вы "mv" файл, все, что вы на самом деле делаете, это отсоединяете первую запись каталога и повторно связываете ее в другом месте.

snoopy -> inode 333 
woodstock -> inode 333

Никакие данные никогда не дублируются / копируются. Вы создайте ссылку snoopy, затем вы создаете ссылку woodstock, а затем удалите ссылку snoopy. (с каталогами все немного иначе, потому что обычно вы не можете создавать каталоги с жесткими ссылками, но даже при этом название "ссылки" просто меняется).

Что делать, если вы переходите с одной файловой системы на другую? Раньше mv просто выдавал ошибку и явно указывал, что вы не можете переместить файл из одной файловой системы в другую. В наши дни кажется, что mv молча копирует данные, а затем удаляет оригинал.

В старые времена, поскольку вы не могли перемещать данные из одной файловой системы в другую, у вас была привычка используя идиомы вроде

tar -cf -. | (cd / new / location && tar -xf -)

затем вы удаляете старые данные. Отчасти причиной использования tar было то, что раньше cp уничтожал такие метаданные, как «это символическая ссылка» и «это жесткая ссылка», и вместо этого вы просто получали бы новые копии этого файла как обычные файлы. Тем не менее, вам нужно дать "cp" flags, чтобы указать ему сохранить такую ​​структуру.

Невозможно избежать «перемещения» большого количества данных, если они находятся из одной файловой системы в другую. Неважно, используете ли вы новый ход, rsync, tar или cpio.

Но если вы храните все данные в одной файловой системе, это:

mv / filesystem-1 / big / directory * / filesystem-1 / big2 /

, который будет очень быстрым, потому что он просто меняет записи каталога, а не перемещает реальные данные.

Есть и другие проблемы, например, что делать, если они есть уже есть файл / каталог в новом месте, а также в исходном местоположении?

0
ответ дан 3 December 2019 в 00:27

Ни один из ответов в этой ветке не подходит для моего варианта использования, поэтому я придумал один из них самостоятельно в качестве скрипта оболочки.

В основе этого лежит эта функция:

recurse() {
    if [ ! -d "$1" ] || [ ! -e "$2" ]; then
        mv -u "$1" "$2" || exit
        return
    fi
    for entry in "$1/"* "$1/."[!.]* "$1/.."?*; do
        if [ -e "$entry" ]; then
            recurse "$entry" "$2/${entry##"$1/"}"
        fi
    done
}

Которую вы можете вызвать следующим образом (для варианта использования OP):

recurse a/b/c2 a2/b/c2

Если источником является файл или каталог, для которого еще не существует место назначения, он просто перемещает его с помощью mv -u. Если источник является каталогом, для которого уже существует место назначения, он перебирает его содержимое и рекурсивно выполняет ту же проверку, за которой следует перемещение | рекурсия для каждого из его членов.

Я использовал -u, потому что мне нужно было только обновить старые файлы и не трогать новые, но вы могли заменить его на -f для безусловного перемещения или -i для интерактивного. Или ничего не меняйте и просто rm -rf ваш источник после того, как скрипт завершит перемещение вещей.

0
ответ дан 11 May 2021 в 18:47

Теги

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