Скрипты Unix Shell для копирования файлов и создания каталогов - PullRequest
2 голосов
/ 30 января 2009

У меня есть исходный каталог, например, / my / source / directory / и целевой каталог, например, / my / dest / directory / , который я хочу отразить с некоторыми ограничениями.

  • Я хочу скопировать файлы, которые соответствуют определенным критериям команды find , например, -ctime -2 (менее 2 дней) в каталог dest, чтобы отразить его
  • Я хочу включить префикс, чтобы я знал, откуда он взялся, например, / source / directory
  • Я хотел бы сделать все это с абсолютными путями, чтобы не зависело, из какого каталога я запускаю
  • Я думаю, отсутствие команд cd тоже хорошая практика.
  • Я хочу создать подкаталоги, если они не существуют

Итак

/my/source/directory/1/foo.txt -> /my/dest/directory/source/directory/1/foo.txt
/my/source/directory/2/3/bar.txt -> /my/dest/directory/source/directory/2/3/bar.txt

Я взломал следующую командную строку, но она кажется немного уродливой, может кто-нибудь лучше?

find /my/source/directory -ctime -2 -type f -printf "%P\n" | xargs -IFILE rsync -avR /my/./source/directory/FILE /my/dest/directory/

Пожалуйста, прокомментируйте, если вы думаете, что я должен добавить эту командную строку в качестве ответа сам, я не хотел быть жадным к репутации.

Ответы [ 6 ]

5 голосов
/ 30 января 2009

Это очень похоже на (закрытый) вопрос: Bash-скрипт, копирующий файлы без перезаписи . Ответ, который я дал, ссылается на решение «find | cpio», упомянутое в других ответах (за исключением временных критериев, но в этом разница между «похожим» и «тем же»), а также описывает решение с использованием GNU «tar».

CTime

Когда я тестировал на Solaris, ни GNU tar, ни (Solaris) cpio не смогли сохранить настройку ctime; действительно, я не уверен, что есть способ сделать это. Например, команда touch может установить atime или mtime или оба, но не ctime. Системный вызов utime() также принимает только значения mtime или atime; он не обрабатывает ctime. Итак, я считаю, что если вы найдете решение, которое сохраняет время, то это решение, вероятно, будет зависеть от платформы. (Странный пример: взломать дисковое устройство и отредактировать данные в inode - не переносимо, требует повышенных привилегий.) Перечитывая вопрос, я вижу, что «сохранение ctime» не является частью требований (phew); это просто критерий того, скопирован файл или нет.

ChDir

Я думаю, что операции 'cd' необходимы, но они могут быть полностью локализованы в скрипте или командной строке, хотя, как показано в приведенном ниже вопросе и в командных строках, вторая из которых предполагает GNU tar .

(cd /my; find source/directory -ctime -2 | cpio -pvdm /my/dest/directory)

(cd /my; find source/directory -ctime -2 | tar -cf - -F - ) |
    (cd /my/dest/directory; tar -xf -)

Без использования chdir() (он же cd) вам потребуются специализированные инструменты или опции для обработки манипуляций с именами путей на лету.

Имена с пробелами, переводы строк и т. Д.

Специфичные для GNU 'find -print0' и 'xargs -0' очень мощные и эффективные, как отметил Адам Хос. Как ни странно, GNU cpio имеет опцию для обработки вывода из 'find -print0', то есть '--null' или его краткой формы '-0'. Итак, используя GNU find и GNU cpio, безопасная команда:

(cd /my; find source/directory -ctime -2 -print0 |
    cpio -pvdm0 /my/dest/directory)

Примечание : Это не перезаписывает ранее существующие файлы в каталоге резервного копирования. Для этого добавьте -u к команде cpio.

Аналогично, GNU tar поддерживает --null (очевидно, без краткой формы -0) и может также использоваться:

(cd /my; find source/directory -ctime -2 -print0 | tar -cf - -F - --null ) |
    (cd /my/dest/directory; tar -xf -)

Обработка имен файлов с помощью нулевого терминатора в GNU чрезвычайно умна и является ценным нововведением (хотя я узнал об этом только недавно, благодаря SO; в GNU tar она была не менее десяти лет).

3 голосов
/ 30 января 2009

Вы можете попробовать cpio, используя режим копирования, -p. Я обычно использую его для перезаписи всех (-u), создания каталогов (-d) и поддержания времени модификации (-m).

find myfiles | cpio -pmud target-dir

Имейте в виду, что find должен создавать относительные имена путей, которые не соответствуют вашим критериям абсолютного пути. Конечно, это может быть «решено» с помощью компакт-диска, который вам тоже не нравится (почему бы и нет?)

(cd mypath; find myfiles | cpio ... )

Скобки порождают подоболочку и сохраняют изменение состояния (т. Е. Переключение каталога) локальным. Вы также можете определить небольшую процедуру, чтобы абстрагироваться от «уродства».

1 голос
/ 30 января 2009

Если вы используете find, всегда используйте -print0 и передайте вывод через xargs -0; ну почти всегда. Первый файл с пробелом в имени будет скрывать скрипт, если вы используете вывод по умолчанию символа новой строки в find.

Я согласен со всеми другими авторами - используйте cpio или tar, если можете. Он будет делать то, что вы хотите, и избавит от хлопот.

0 голосов
/ 06 февраля 2009

! / USR / бен / ш

скрипт для копирования файлов с одинаковой структурой каталогов "

echo "Пожалуйста, введите полный путь к исходному DIR (начиная с / и заканчивая /):" читать spath

echo "Пожалуйста, введите полный путь к месту назначения (начиная с / и заканчивая /):" читать dpath

си = echo "$spath" | awk -F/ '{print NF-1}'

для имени в find $spath -type f -print делать CDIR = echo $fname | awk -F/ '{ for (i='$si'; i<NF; i++) printf "%s/", $i; printf "\n"; }' if [$ cdir]; затем если [ ! -d "$ dpath $ cdir"]; затем mkdir -p $ dpath $ cdir фи фи

cp $ fname $ dpath $ cdir

сделано

0 голосов
/ 30 января 2009
#!/bin/sh

SRC=/my/source/directory
DST=/my/dest/directory

for i in $(find $SRC -ctime -2 -type f) ; do
    SUBDST=$DST$(dirname $i)
    mkdir -p $SUBDST
    cp -p $i $SUBDST
done

И я полагаю, поскольку вы хотите включить «откуда это», вы будете использовать разные исходные каталоги. Этот сценарий можно изменить, чтобы он использовал исходный каталог в качестве аргумента, просто заменив каталог SRC = / my / source / на SRC = $ 1

EDIT: удален избыточный оператор if.

Не работает, если в именах файлов есть пробелы.

0 голосов
/ 30 января 2009

Альтернативой является использование смолы, (cd $ SOURCE; tar cf -.) | (cd $ DESTINATION; tar xf -)

EDIT: Ах, я пропустил немного о сохранении CTIME. Я полагаю, что большинство реализаций tar сохранит mtime, но если сохранение ctime критично, то cpio действительно единственный путь.

Кроме того, некоторые реализации tar (в частности, GNU tar) могут выбирать файлы для включения на основе atime и mtime, хотя, по-видимому, не ctime.

...