Pull to refresh

Comments 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 и не обращаясь при этом к репозиторию. По этой причине была необходимость обрабатывать и субдиректории.
Мне не очень подходило, т.к. нужна была локальная копия с локальными изменениями.
Откройте для себя бранчи и 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
Не понимает регулярное выражение
Но ведь вы тоже решили задачу, отличную от заявленной. А если у меня в папке есть пара гигабайтных файлов, которые я копировать не хочу, и для которых в 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
UFO just landed and posted this here
UFO just landed and posted this here
Вообще есть штатное решение
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/'{}' \;

Sign up to leave a comment.

Articles