Я пытаюсь синхронизировать файлы из системы A в систему B. Однако файлы реорганизованы в другую структуру каталогов, что затрудняет использование rsync.
Есть ли способ указать rsync игнорировать каталоги и работать только с именами файлов? Имена файлов уникальны, каталоги - нет. Структура каталогов не фиксирована, поэтому я не могу просто заменить их. Я уже думал о написании сценария, который удаляет информацию о каталоге, но я не уверен, что это вызовет другие проблемы.
Фактически, да, я хочу сгладить структуру каталогов. Судя по ответам, я, вероятно, не хочу использовать rsync.
Я работаю с видео, третьи стороны создают структуру каталогов (и им должно быть разрешено изменять структуру каталогов, когда это необходимо). Эти видео необходимо синхронизировать с основной файловой системой. Имена файлов не подлежат изменению. Так что что-то вроде разницы между "find. | Rip-out-path" в обеих системах и diff может помочь; но мне было интересно, есть ли у rsync какой-то волшебный флаг, чтобы вообще игнорировать каталоги при рекурсии - аналогично параметру -p в патче.
Вы облажались, или меньше. Пока вы можете сказать rsync
для рекурсии и других игр, вы не можете заставить его искать в дереве файловой системы файл с таким же именем на другом конце.
Я бы сказал, что вам нужно будет иметь небольшой сценарий оболочки на дальнем конце, который, учитывая голый файл, возвращает полный путь к файлу в этом конце, а затем повторяет каждый файл на локальном конце, вызывая этот сценарий оболочки для получения удаленного пути, а затем выполняя rsync
один ... файл ... в ... в ... время ...
Это, конечно, при условии, что все файлы уже существуют на дальнем конце ... куда их поместить, если их там даже нет? Их пропускают?
Я найду того, кто придумал эту дурацкую схему хранения файлов, и сломаю ему пальцы.
Вероятно, самый простой способ решить проблему перемещения всех файлов из дерева каталогов в один напрямую - это использовать find с параметрами -type и -exec. Параметр -type ограничивает вывод определенным типом записи каталога (f для файла, d для каталога и т. Д.). Параметр -exec передает найденное имя (как {}) в командную строку с параметрами.
Вот пара примеров:
find /directory/top/ -type f -exec rsync {} desthost:/destdir
find /directory/top/ -type f -exec scp {} desthost:/destdir
SOURCE_DIR=/path/to/lots/of/dirs/and/files
LINK_PATH=/path/to/store/all/files/as/symlinks/in/single/directory
DEST_PATH=/path/to/place/all/files/in/single/directory/with/no/child/directories
find $SOURCE_DIR -type f -print0 | xargs -0 cp -s --target-directory=$LINK_PATH
rsync -Lts $LINK_PATH/* $USER@$DEST_IP:$DEST_PATH
как насчет опции --fuzzy в rsync? Я не знаю, сработает ли это в вашем случае, но вы можете попробовать.
В общем случае я все еще придерживаюсь другого ответа "сломать палец", но у меня есть другое решение для вашей конкретной ситуации, которое, как я понимаю:
Я думаю, вы запускаете rsync в удаленные каталоги (например, /storage/.remotes/client1/
, /storage/.remotes/client2/
и т.д.) для каждой из удаленных файловых систем, которые вы синхронизируете, а затем у вас есть сценарий, который нормализует имена файлов в вашу собственную иерархию (при условии, что вы можете алгоритмически описать свою организационную схему), и который вы запускаете через все после того, как rsync сделает это вещь для символическая ссылка в клиентские удаленные хранилища. Если вы не можете описать желаемую иерархию алгоритмически, то, полагаю, вам придется создать символическую ссылку вручную (или, по крайней мере, с некоторым уровнем человеческого участия, даже если есть поддержка инструментов).
Единственная трудность заключается в том, что пульт переставляет свои вещи, но тогда вы просто обнаруживаете теперь сломанные символические ссылки, находите новые местоположения имен файлов (при условии, что имена не изменились, только местоположения).
Если все файлы находятся в одной файловой системе, может быть проще жестко связать их все с одним каталогом на стороне источника, а затем выполнить синхронизацию этого одного каталога. Что-то вроде:
#!/bin/bash
set -e
mkdir flattened_dir
find sourcedir1 sourcedir2 sourcedir3 -type f -exec ln -t flattened_dir/ {} +
rsync -avP flattened_dir/ remote:destination/
rm -r flattened_dir
P.S. Если find
не поддерживает +
, ты можешь использовать \;
Точно так же я хотел вытащить файлы из каталогов и поместить их в один плоский каталог, используя только их имя файла. Решение такое:
find /directory/top/ -type f -exec rsync -av `basename {}` desthost:/destdir
Вы также можете использовать некоторые другие флаги в find для ограничения того, какие файлы вы хотите ... например, возможно, вам нужны только файлы JPG:
find /directory/top/ -type f -name "*.JPG" -exec rsync -av `basename {}` desthost:/destdir
Вы можете использовать Bash globopt (**
) для рекурсивного сопоставления каждого файла, как описано в эта почта.
Поскольку вы вызываете rsync только один раз, он должен быть намного быстрее, чем другие подходы, в которых вы вызываете команду для каждого файл (как find ... -exec
).
Вы можете копировать файлы из разных исходных папок в одну целевую папку (плоскую) без переноса исходных вложенных папок, используя команду:
find source_dir -name "*.pdf" >/tmp/xx.txt
rsync -t -v --no-relative --files-from=/tmp/xx.txt / desthost:/destdir
rm -f /tmp/xx.txt
Вы можете создавать по одному каталогу за раз, если это дает вам хороший размер пакета файлов за один вызов процесса rsync. Так что-то вроде:
find . -type d | while read dir; do rsync -a $dir/* user@host:flatdir; done