- PVSM.RU - https://www.pvsm.ru -
Топик написан в ответ на похожий [1].
Автор оригинального топика предлагает решить задачу в лоб — а именно, скопировать все файлы а потом удалить не нужные. Это может быть неплохим решением, если вам, конечно, не нужно скопировать всю домашнюю папку на флешку, за исключением вашей коллекции видео.
Но главная проблема этого подхода в другом — он не соответствует идеологии unix: сложные задачи решаются комбинацией простых утилит.
А теперь о том, как нужно делать.
Решение любой комплексной задачи начинается с разбора её на составные части. Итак нам нужно скопировать некоторый набор файлов предварительно его отфильтровав.
Значит — получение списка файлов, фильтрация, копирование.
Обычно мы просматриваем список файлов программой ls. Её вывод выглядит примерно так:
$ ls -1
dir1
dir2
file1.bin
file2.txt
Подходит ли там такой вывод? Нет, потому, что в нем недостаточно информации — нам нужно копировать файлы рекурсивно, значит для нас было-бы гораздо удобнее если первая в нашей цепочке программа выдала там имена файлов вместе с путями.
Следующая программа, которая приходит на ум — find
$ find ./
./
./dir1
./dir1/file7.txt
./dir2
./file1.bin
./file2.txt
Уже лучше но в вывод попали и директории, а они нам не нужны. Попробуем так:
$ find ./ -type 'f'
./dir1/file7.txt
./file1.bin
./file2.txt
Вот то, что там нужно. Список файлов.
Этот список файлов нужно отфильтровать. Перенаправим [2] вывод нашей предыдущей комманды в программу grep.
$ find ./ -type 'f' | grep 2
./dir2
./file2.txt
Хорошо, но в условиях задачи стоит исключать файлы, так что немного поменеяем наш конвейер [3]
$ find ./ -type 'f' | grep -v 2
./dir1/file7.txt
./file1.bin
Первые две части выполнены.
Из man-страницы [4] для команды cp мы можем узнать, что исходный файл нужно передавать программе cp в качестве аргумента, а мы пока можем только перенаправить список на стандартный ввод [5].
Применим утилиту xargs — она принимает стандартный ввод и вызывает указанную программу с параметрами из стандартного ввода. Итак:
$ find ./ -type 'f' | grep -v 2 | xargs -n 1 -I % cp --parents "%" /path/to/dest/dir/
-n 1 значит, что только одна строка из стандартного ввода подставляется в комманду, а -I % — определяет символ, который будет заменен в целевой комманде на строчку из стандартного ввода. В нашем случае это будет
cp --parents "./dir1/file7.txt" /path/to/dest/dir/
cp --parents "./file1.bin" /path/to/dest/dir/
Задача решена.
Я надеюсь что это описание поможет правильно подходить к решению как таких простых так и более комплексных задач.
Хочется отметить, что
tar --exclude=2 -cf - ./ | ( cd /path/to/dest/ && tar -xvf - )
Автор: iamwizard
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/linux/14413
Ссылки в тексте:
[1] похожий: http://habrahabr.ru/post/150813/
[2] Перенаправим: http://ru.wikipedia.org/wiki/%D0%9F%D0%B5%D1%80%D0%B5%D0%BD%D0%B0%D0%BF%D1%80%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_(UNIX)
[3] конвейер: http://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BD%D0%B2%D0%B5%D0%B9%D0%B5%D1%80_(UNIX)
[4] man-страницы: http://ru.wikipedia.org/wiki/Man
[5] стандартный ввод: http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D0%B0%D0%BD%D0%B4%D0%B0%D1%80%D1%82%D0%BD%D1%8B%D0%B9_%D0%B2%D1%8B%D0%B2%D0%BE%D0%B4
Нажмите здесь для печати.