Comments 67
Мало того, rsync — не единственный способ. Однако, во-первых, он не в входит в стандартную поставку множества дистрибутивов. А во вторых — цель топика не показать одну строчку «как сделать», а рассказать, о том как самому искать решения не изобретая велосипедов.
Или вы думаете что топику не место на хабре?
Или вы думаете что топику не место на хабре?
этому топику — место. исходному — место в QA
этому топику — местону скажем так, вроде информация годная, но вот статьёй это назвать тяжело. Это можно свернуть в комментарий к предыдущей «статье», до фразы: «смотри на find и прочитай в man'е, что у cp есть ключ --parents».
а у find есть ключи name и exec. а так же возможность комбинировать ключи через опции -o, -a и скобки. Но кому это интересно?) Читать маны — не модно.
«читаю man'ы — $10, читаю man'ы с выражением — $15» ©
exec, если я не ошибаюсь, есть только в GNU find
-name и ещё -regex, если уж говорить об исходной задаче — укоротили-бы решение, но главной целью было показать возможности конвейера.
-name и ещё -regex, если уж говорить об исходной задаче — укоротили-бы решение, но главной целью было показать возможности конвейера.
Конвейер не предназначен для передачи имён файлов. В ссылке ниже подробное объяснение этому чуду.
exec есть и в POSIX версии. Даже + на конце exec'a там есть, если я не ошибаюсь.
exec есть и в POSIX версии. Даже + на конце exec'a там есть, если я не ошибаюсь.
Да, вы правы про exec, видимо у меня сложилось неверное впечатление после того как лет 10 назад я не нашел его в man-e
Ссылка не съелась. Я просто ссылался на свой комментарий ниже.
$ man cp | grep parents | wc -l
0
0
Я бы сказал, что это не статья, а часть серии статей о том как писать скрипты. И видя заголовок «как решить то-то», я жду решение, а не экскурс в анализ и знание различных утилит окружения GNU.
Вы знаете, когда я только начинал изучать unix-like системы, главное чему я был поражен — это следование принципу «от понимания к действию» и прочитав одну статью становилось возможным решать весь класс подобных проблем. И этим статьи отличались от «howto» которые как вы и предлагаете — описывали последовательность действий необходимую для достижения конкретного результата в конкретных условиях.
Однако, мне кажется, что хабр уж точно не место для однострочных howto. А эта информация, возможно, поможет кому нибудь понять как решаются такие задачи.
Однако, мне кажется, что хабр уж точно не место для однострочных howto. А эта информация, возможно, поможет кому нибудь понять как решаются такие задачи.
Отличная статья, познавательная. Спасибо!
На самом деле многому учит.
На самом деле многому учит.
Для подстановки аргументов ещё можно использовать конструкцию $() внутрь которой мы помещаем файнд с грепом, а всё это целиком отдаём cp в качестве аргумента.
Читать до полного просветления.
Автору исходного поста, кстати, тоже не помешало бы.
А ещё не помешало бы почитать man find и использовать вместо find | grep -v кошерную конструкцию
И вообще, если вы такой противник rsync'a, то задача решается одним find'ом на раз два:
А в целом, в статье я увидел лишь полное нежелание читать маны, стремление использовать странные решения и преподносить это как способ «как самому искать решения не изобретая велосипедов».
Автору исходного поста, кстати, тоже не помешало бы.
А ещё не помешало бы почитать man find и использовать вместо find | grep -v кошерную конструкцию
find /path ! -name "*exclude*"
И вообще, если вы такой противник rsync'a, то задача решается одним find'ом на раз два:
find /path -type f ! -name "*exclude*" -exec cp --parents -t /target/dir "{}" \+
А в целом, в статье я увидел лишь полное нежелание читать маны, стремление использовать странные решения и преподносить это как способ «как самому искать решения не изобретая велосипедов».
Вы правы, в случае, если в качестве исходного списка файлов у нас выступает файловая система — можно использовать find и множество других утилит. Топиком я хотел показать как решать подобный класс задач — комбинированием утилит. Ведь как только мы начинаем брать список файлов, например из файла, find нам уже не поможет.
Вообщем, судя по обилию комментариев с непониманием исходной цели топика, что-то было написано не так и его лучше убрать.
Вообщем, судя по обилию комментариев с непониманием исходной цели топика, что-то было написано не так и его лучше убрать.
В таком случае, стоило сделать акцент на этом в самом топике. В противном случае тонны конструктивной критики выльются на вас. И комментирующие будут правы.
А в случае чтения списка из файла, стоит тогда включить проверку, есть ли вообще такой файл, и не сломает ли что запускаемая команда.
Вы просто выбрали неудачный пример для того, что хотите продемонстрировать.
А в случае чтения списка из файла, стоит тогда включить проверку, есть ли вообще такой файл, и не сломает ли что запускаемая команда.
Вы просто выбрали неудачный пример для того, что хотите продемонстрировать.
Если вы хотите что-то продемонстрировать, как то «брать список файлов, например из файла» — так и делайте именно так. Не надо подавать дурных примеров. Те, кто будет это читать, скорее всего не знают о том, что умеет find сам по себе, а стоило бы.
Внес изменения в исходный топик, добавлен дискламер, и готовый рецепт для этой конкретной задачи.
Однако не могли-бы Вы пояснить почему вы считаете использование более универсальных методов дурным примером?
Однако не могли-бы Вы пояснить почему вы считаете использование более универсальных методов дурным примером?
Вы же хотите научить хорошему? Тогда надо учить использовать для каждой задачи подходящий инструмент. Я вполне допускаю, что когда времени нет, лень посмотреть ман, и набрал в консоли первое, что в голову пришло — это одно, но не надо это показывать в качестве обучающего материала. Автор, который осмелился учить чему-то остальных, должен нести большую ответственность.
off
Может быть я брюзжу тут как старый дед =), но уж больно универсалов много развелось, орудующих одним молотком по всем гвоздям, специалистов вот только не найти. И куча how-to в сети только способствует.
Насколько я понял, проблема в том, что очень общую тему я объяснил на примере излишне конкретной задачи.
Думаю, стоит написать отдельный топик, с большим количеством теории и рассмотрев больше примеров, про который нельзя будет сказать что «это решается одной командой». Но так уж получилось, что я собрался написать статью именно в ответ на тот топик.
Думаю, стоит написать отдельный топик, с большим количеством теории и рассмотрев больше примеров, про который нельзя будет сказать что «это решается одной командой». Но так уж получилось, что я собрался написать статью именно в ответ на тот топик.
off reply
Мне кажется, что непрофессионализм, частным случаем которого является поверхностный подход (естественно, подразумевая ситуации, где такой подход не допустим) — является скорее свойством личности, а не результатом неправильного обучения
Никогда не понимал, что означает конструкция
"{}" \+
в конце find-а?Очень полезная штука. find с \; запускает по одному процессу на каждый найденный файл. find с \+ на конце группирует файлы и запускает по одному процессу на много файлов. Экономия времени и ресурсов, однако. Появилась лет 7 назад.
С вас 10$ за краткую выжимку из man'а =)
С вас 10$ за краткую выжимку из man'а =)
man find говорит нам, что:
Строка `{}' будет заменена именем текущего обрабатываемого файла
У меня этот вариант работает и без слеша. Но безопаснее/привычнее экранировать.
Вообще есть 2 варианта запуска find -exec:
Попытка скопировать это и выполнить в шелле провалится, т.к. шелл съест «; ». Чтоб символ дошёл до find, его экранируют от шелла слешем.
Ещё можно взять в кавычки с тем же эффектом:
Вообще есть 2 варианта запуска find -exec:
find -exec echo {} ;
find -exec echo {} +
Попытка скопировать это и выполнить в шелле провалится, т.к. шелл съест «; ». Чтоб символ дошёл до find, его экранируют от шелла слешем.
Ещё можно взять в кавычки с тем же эффектом:
find -exec echo {} ';'
Вместо 'xargs cp --parents' можно использовать 'cpio -pd'
Необязательно писать
find ./
, достаточно find .
. Меньше набирать, и выглядит красивее.Годная статья. Спасибо.
Как раз недавно задавался подобным вопросом.
Вообще надо будет ознакомиться и начать использовать такие true-юниксойдные штуки, как sed, awk, xargs, find, for, узнать больше о любимом grep. :) Отпугивает то, что выглядит всё это по-шамански сложно.
Как раз недавно задавался подобным вопросом.
Вообще надо будет ознакомиться и начать использовать такие true-юниксойдные штуки, как sed, awk, xargs, find, for, узнать больше о любимом grep. :) Отпугивает то, что выглядит всё это по-шамански сложно.
Пожалуйста.
Не бойтесь, главное преимущество этого подхода то, что каждая отдельная утилита достаточно проста.
Ваш любимый grep выполняет одну функцию — фильтрует. Просто делает он это кучей разных способов, но вам-же не обязательно изучать их все сразу — просто имейте ввиду что grep может отфильтровать всё что угодно, а конкретные параметры всегда можно посмотреть в man в тот момент, когда они понадобятся.
Не бойтесь, главное преимущество этого подхода то, что каждая отдельная утилита достаточно проста.
Ваш любимый grep выполняет одну функцию — фильтрует. Просто делает он это кучей разных способов, но вам-же не обязательно изучать их все сразу — просто имейте ввиду что grep может отфильтровать всё что угодно, а конкретные параметры всегда можно посмотреть в man в тот момент, когда они понадобятся.
А у меня есть файлы с переводами строк в именах (да, перевод строки — допустимый символ). Как там grep отработает? Подсказываю: неправильно :)
Значит вам, очевидно, нужно будет использовать способы отличные от описанного в основной части топка. Например — один из готовых рецептов в заключении.
Я к этому и веду, что стоит написать, что всё это хорошо, но неверно. А сейчас написано «Задача решена», как будто это верное решение. А в заключении эквивалентное решение.
Вы правы, исправил формулировку.
На самом деле тема многострочной фильтрации не сказать, что хорошо раскрыта. На последнюю задачу выковыривания данных из постраничного вывода я убил приличное количество времени, а от переводов избавлялся с помощью tr`а, что ну никак нельзя назвать элегантным решением. Был бы рад увидеть обзорную статью на эту тему, например. Начинание то у вас хорошее.
Если найду время написать, то обязательно затрону тему сепараторов и экранирования
Декомпозиция требует первым делом выписать все файлы, а спасает от первичного формирования громадной простыни юниксовая потоковость команд, да? Без возможности организовать поток такой подход был бы чреват неэффективным использованием ресурсов, для предварительного формирования того огромного списка…
некогда озаботился проблемой сложного копирования файлов, пробовал xcopy, robocopy итп и пришел к выводу что во многих ситуациях нужно писать скрипт. Тогда сел и в качестве развлечения написал свою консольную программку для копирования. Основной фишкой которой было разделение ключей для копирования на ключи для файлов и пля папок. Так же реализовал возможность задания множества масок для каждого ключа. С тех пор перестал пользоваться вышеуказанными утилитами и по мере нужды добавляю в свою прогу новые возможности. На данный момент уже получился хороший список, и точно могу сказать, то что в этой проге можно сделать одним запуском проги в других, без написания скрипта не получится. Кому интересно тут последняя альфа. Если кому что то надо добавить обращайтесь.
маленький пример:
скопирует файлы с масками *.txt *.doc *.pdf исключив файлы с масками __*.pdf bak*.doc ~*.pdf из папок с масками Doc* Scan пропуская в них папки с масками Temp Tmp
где:
если надо перезаписать то добавить /OF
если в каких то папках ненадо проверять маски файлов то /XDMF или /XDMD
и.т.п
в этой программке Вас многое, надеюсь приятно, удивит
copymik "c:\Папка откуда" "d:\Папка куда" /MF *.txt *.doc *.pdf /MD Doc* Scan /XCF __*.pdf bak*.doc ~*.pdf /XCD Temp Tmp
скопирует файлы с масками *.txt *.doc *.pdf исключив файлы с масками __*.pdf bak*.doc ~*.pdf из папок с масками Doc* Scan пропуская в них папки с масками Temp Tmp
где:
Заголовок спойлера
[/MF[ МаскаФайла1[ МаскаФайла2[ ....]]]] Маска для копирования файлов (по умолчанию маска * — все)
[/MD[ МаскаПапки1[ МаскаПапки2[ ....]]]] Маска для копирования папок (по умолчанию маска * — все)
[/XCD [МаскаПапки1[ МаскаПапки2[ ....]]]] Не копировать папки с указанными масками (по умолчанию маска * — все)
[/XCF [МаскаФайла1[ МаскаФайла2[ ....]]]] Не копировать файлы с указанными масками (по умолчанию маска * — все)
[/MD[ МаскаПапки1[ МаскаПапки2[ ....]]]] Маска для копирования папок (по умолчанию маска * — все)
[/XCD [МаскаПапки1[ МаскаПапки2[ ....]]]] Не копировать папки с указанными масками (по умолчанию маска * — все)
[/XCF [МаскаФайла1[ МаскаФайла2[ ....]]]] Не копировать файлы с указанными масками (по умолчанию маска * — все)
если надо перезаписать то добавить /OF
если в каких то папках ненадо проверять маски файлов то /XDMF или /XDMD
Заголовок спойлера
[/XDMD МаскаПапки1[ МаскаПапки2[ ....]]] Не проверять маску папки для подпапок с указанной маской (будет использована маска * — все)
[/XDMF МаскаПапки1[ МаскаПапки2[ ....]]] Не проверять файловую маску для подпапок с указанной маской (будет использована маска * — все)
[/XDMF МаскаПапки1[ МаскаПапки2[ ....]]] Не проверять файловую маску для подпапок с указанной маской (будет использована маска * — все)
и.т.п
в этой программке Вас многое, надеюсь приятно, удивит
Ребята подскажите как мне исправить.
У меня в результате находит файл но при копировании подставляет «To: office@vp.com». А как сделать так что бы подставляло только пусть?
find /home/vmail/vp/cur/ -type f -exec grep -H "To: office@vp.com" {} \; | xargs -n 1 -I % cp --parents "%" /home/OFFICE/
У меня в результате находит файл но при копировании подставляет «To: office@vp.com». А как сделать так что бы подставляло только пусть?
Sign up to leave a comment.
Как правильно скопировать файлы и папки исключая некоторые из них