Как стать автором
Обновить

Комментарии 43

Хм, а если

ls folder | grep -v [regexp] | xargs cp -t destination

где:
folder— исходная директория
destination — конечная
[regexp] — собственно, регулярка

Флаг -v у grep делает следующее, если кто-нибудь запамятовал (выдержка из man):
-v, --invert-match Selected lines are those not matching any of the specified patterns.
Вы пробовали запускать? Чёто у меня оно не хочет работать:
ls /web/test/www | grep -v .*\.svn.* | xargs cp -t /web/test/tmp
cp: cannot stat `app': No such file or directory
cp: cannot stat `libraries': No such file or directory
cp: cannot stat `public': No such file or directory
Для текущей директории запустил:

ls $1 | grep -v file1 | xargs cp $1 destination/$1

Успешно переместило все файлы, кроме file1 в подпапку destination.

Ваше решение слишком громоздко, а «сначала копирует всё, а потом удаляет лишнее» это лишние телодвижения.
Моё решение обрабатывает не толь файлы, но и все папки, включая подпапки.
Вообще моей изначальной целью было создание копии проекта, избавляясь от директорий .svn и не обращаясь при этом к репозиторию. По этой причине была необходимость обрабатывать и субдиректории.
А разве svn export не подходит?
Мне не очень подходило, т.к. нужна была локальная копия с локальными изменениями.
Откройте для себя бранчи и D-RCS, например, git.
А в кавычки кто брать regexp будет? И этот человек пишет статью, состоящую целиком и полностью из одного скрипта. Вы бы хоть не позорились ужасным синтаксисом и не соблюдением элементарных правил!
Понимаю, Вы — «системный администратор Linux / Windows»

А я — … новичёк в linux-е и это мой первый пост на хабре, но может кому-то похожему на меня он окажется полезным…

Исходя из вышесказанного, могли бы научить «как правильно», а не наезжать.
Пожалуйста, вот в шапке этой темы на одном форуме есть уйма полезных ссылок. По прядку переходите по каждой ссылке и вдумчиво изучаете.
Спасибо, Учитель!
мне вот отсюда много пригодилось
легко находится ищется по ключевым «advanced bash scripting guide»
Спасибо, почитаю на досуге.
вместо ls folder надо просто написать find folder, это и будет решением задачи. find выводить файлы, рекурсивно просматривая каталоги.
find folder | grep -v [regexp] | xargs cp -t destination
  • не сохраняется структура папок
  • не переписываются подпапки
Да, вы правы. find как раз подходит для решения задачи ТС.
Проблема еще не решена. cp ругается на каталоги, но флаг -r использовать нельзя, потому что он тогда скопирует ненужные файлы, а пропускать каталоги нельзя, потому что пользователь хочет скопировать пустые каталоги тоже.
Еще есть другая проблема. Если писать не относительный путь в find, то в целевом каталоге будут создаваться каталоги, соответствующие полному пути исходных файлов.
Универсальное решение:

SRC=~/work/soruce; DEST=~/work/test; REGEXP=js; pushd $SRC; for I in $(find ./ | grep -v "$REGEXP"); do if [ -d $I ]; then mkdir $DEST/$I; else cp $I $DEST/$I; fi; done; popd 2>/dev/null

PS. прошу прощения, что наплодил комментов (мысли приходят не сразу) :)
Не универсально:

find ./

У Вас видимо текущей директорией является ~/work/soruce
По этому у Вас и работает
Если вы попробуете сменить текущую директорию, то повалится
pushd — для временного перехода в нужную папку. внимательней ;)
Да, Вы правы.
Решение для копирования файлов, начиная от текущего каталога

DEST=~/work/test; REGEXP=js; for I in $(find ./ | grep -v "$REGEXP"); do if [ -d $I ]; then mkdir $DEST/$I; else cp $I $DEST/$I; fi; done 2>/dev/null
DEST=~/work/test; REGEXP=js; find ./ | grep -v "$REGEXP" | cpio -pd $DEST
cp -r path1/[^regexp] path2
не пойдёт?
Не понимает регулярное выражение
Но ведь вы тоже решили задачу, отличную от заявленной. А если у меня в папке есть пара гигабайтных файлов, которые я копировать не хочу, и для которых в destination места не хватит?
Я с этим и не спорю. Сам думаю о том, что нужно более «прямое» решение.
Если у кого-нибудь на уме есть более приемлемое решение, милости прошу.

А «rsync --exclude=REGEX ...» чем не устраивает?
Вот так работает:

rsync -r --exclude=PATTERN from/ to/

Спасибо!
Если нужно просто убрать папки */.svn, */.cvs и похожие, то достаточно использоваться rsync -C from/ to/
тем что его эксклуды — не регулярки
Ну, может там и не полноценные регулярные выражения, но в большинстве реальных случаев этого будет достаточно.
ну или аналогично rsync
tar cf — --exclude=PATTERN * | tar xf — -C newdir

думаю на www.commandlinefu.com можно еще десяток способов найти
ну и еще общий вариант — сделать список фалов, проредить его грепом и скормить как источник того что нужно копировать любой из программ
#!/bin/bash
if [ $# -lt 3 ] ; then
    echo "cpexclude usage: pathFrom pathTo excludeRegex"
    exit 0
fi
pathFrom="$1"
pathTo="$2"
excludeRegex="$3"
# Copy everything
find "$pathFrom" -type f -not -regex "$excludeRegex" | while read A ; do {
[[ -d "$pathTo/${A%/*}" ]] || mkdir -p "$pathTo/${A%/*}"
cp -a "$A" "$pathTo/${A%/*}"
}
done
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Вообще есть штатное решение
find . ! -iregex '.*gz' -exec cp -a '{}' \;

Это плохой пример чисто для наглядности, плохой потому что надо сначала копировать структуру директорий а потом фаилы по регекспу. Но идея думаю понятна.
А еще я тут недавно спрашивал в QA есть ли ресурс для bad practice по администрированию.
Вот собственно с этого топика пожно начать наполнять подобный блог на хабре.

Автору как новичку простительно ошибаться — видно что мозг работал просто рано остановился, но остальные должны увидеть предупреждение «НЕ ДЕЛАЙ ТАК» прежде чем начнут использовать этот код.
На всякий случай напишу полное решение
find plpbt-5.0.14/ -type d -exec mkdir -p dest/'{}' \; find plpbt-5.0.14/ -type f ! -iregex '.*iso' -exec cp '{}' dest/'{}' \;

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