У меня есть следующая структура каталогов:
dir1
py1.py
py2.py
subdir1
file1.py
anotherfile.txt
subdir2
file2.py
animage.png
Я хотел бы скопировать структуру папок и *.py файлы (кроме тех, которые принадлежат непосредственно dir1) к новому каталогу на том же уровне как dir1. Таким образом, я ищу это:
dir2
subdir1
file1.py
subdir2
file2.py
Я попробовал (от слоя выше dir1):
mkdir dir2
cp -r *.py ../dir2
Но это только скопировало *.py файлы с dir 1 в dir2 и проигнорировало подкаталоги.
Вы могли использовать шарик оболочки, с --parents
опция cp
Напр. данный
$ tree dir1 dir2
dir1
├── py1.py
├── py2.py
├── subdir1
│ ├── anotherfile.txt
│ └── file1.py
└── subdir2
├── animage.png
└── file2.py
dir2
2 directories, 6 files
(отметьте это dir2
уже существует), затем
$ cd dir1
$ cp --parents -t ../dir2 **/*.py
$ cd ..
дает
$ tree dir1 dir2
dir1
├── py1.py
├── py2.py
├── subdir1
│ ├── anotherfile.txt
│ └── file1.py
└── subdir2
├── animage.png
└── file2.py
dir2
├── subdir1
│ └── file1.py
└── subdir2
└── file2.py
4 directories, 8 files
Я использовал globstar
шаблон **
но если только необходимо убывать один уровень, Вы могли бы использовать основное *
подстановочный знак для подкаталогов.
Можно сделать это с find
и cpio
, просто cd
в dir1
и выполненный это:
find . -mindepth 2 -type f -name "*.py" -print | cpio -pdm ../dir2
find .
запустится в текущем каталоге т.е. dir1
-mindepth 2
проигнорирует содержание текущего каталога т.е. dir1
и включайте содержание его подкаталогов.-type f -name "*.py" -print
будет включать только файлы с .py
расширение.cpio -pdm
скопирует. -p
создает список файлов, -d
создает каталоги по мере необходимости и -m
устанавливает корректное время изменения на каталогах.
../dir2
создаст каталог (если он не будет существовать), названный dir2
каждый выравнивает рядом с dir1
и скопируйте все в него.
Поскольку ссылочный человек находит и человек cpio.
Всего наилучшего
Хорошо, я не мог найти способ сделать CP, или rsync собой делают то, что Вы хотите, таким образом, я придумал:
for n in dir1/* ; do ls ${n}/*.py >/dev/null 2>&1 ; if [[ $? == 0 ]]; then mkdir dir2/${n/dir1\//} ; cp ${n}/*.py dir2/${n/dir1\//} ; fi ; done
Расположение с отступом его правильно делает его более читаемым:
for n in dir1/*
do
ls ${n}/*.py >/dev/null 2>&1
if [[ $? == 0 ]]
then
mkdir dir2/${n/dir1\//}
cp ${n}/*.py dir2/${n/dir1\//}
fi
done
Так, что я делаю, просматривает dir1, предполагая, что каждый файл является каталогом и пытающийся перечислить любые *.py файлы (с выводом и ошибкой, исчезающей в/dev/null). Очевидно, пробуя это за py1.py и py2.py перестанет работать, потому что они не каталоги. Это должно также перестать работать для любых каталогов, которые не имеют никаких *.py файлов в них.
Это означает это, когда мы находимся в если, результат предыдущей команды ($?) должно быть что-то другое, чем 0, и мы ничего не делаем. Для subdirs в dir1 список должен успешно выполниться, и таким образом, $? будет 0, таким образом, мы выполняем бит в цикле. Это просто создает subdir в dir2 (не забывающий ничем заменять "dir1 /") и копирует любые *.py файлы через.
Это - конечно, не единственный способ сделать это, и в то время как это работает на пример, Вы дали, это не работает, если у Вас есть дополнительные уровни subdirs внутри subdirs. (например. dir1/subdir1/subsubdir1/*.py
не будет скопирован через),
Использовать rsync
:
mkdir dir2
rsync -amv --include '*/' --include '*/*.py' --exclude '*' dir1/ dir2
Это скопирует все .py
файлы, начинающие со второго уровня.
-m
постарайтесь не создавать пустые каталоги.--include '*/'
Включайте все каталоги--include '*/*.py'
Включайте все .py
файлы, запускающиеся на втором уровне '/*/*.py'
если Вы хотите включать только второй уровень .py
файлы--exclude '*'
Исключите все, что не включено.