Позволяет говорят, что у меня есть следующая структура дерева каталогов:
./Original
├── Dir1
│ ├── Objects
│ └── Textures
├── Dir2
│ ├── SubDir1
│ │ └── SubSubDir1
│ │ ├── Objects
│ │ └── Textures
│ └── SubDir2
│ ├── Objects
│ └── Textures
└── Dir3
├── Objects
├── SubDir1
│ ├── Objects
│ └── Textures
└── Textures
И у меня также есть подобная структура (это - на самом деле копия Исходного Каталога без каталогов Objects и Textures:
./Copy
├── Dir1
├── Dir2
│ ├── SubDir1
│ │ └── SubSubDir1
│ └── SubDir2
└── Dir3
└── SubDir1
Как я перемещаю все каталоги Objects и Textures и их файлы от оригинала до соответствующего положения в Каталоге Копии? Это должно быть похожим на это когда завершенный:
./Original
├── Dir1
├── Dir2
│ ├── SubDir1
│ │ └── SubSubDir1
│ └── SubDir2
└── Dir3
└── SubDir1
./Copy
├── Dir1
│ ├── Objects
│ └── Textures
├── Dir2
│ ├── SubDir1
│ │ └── SubSubDir1
│ │ ├── Objects
│ │ └── Textures
│ └── SubDir2
│ ├── Objects
│ └── Textures
└── Dir3
├── Objects
├── SubDir1
│ ├── Objects
│ └── Textures
└── Textures
Вещи заметить:
Используйте эту команду для создания стартовой структуры:
mkdir -p Original/Dir1/Objects Original/Dir1/Textures Original/Dir2/SubDir1/SubSubDir1/Objects Original/Dir2/SubDir1/SubSubDir1/Textures Original/Dir2/SubDir2/Objects Original/Dir2/SubDir2/Textures Original/Dir3/Objects Original/Dir3/Textures Original/Dir3/SubDir1/Objects Original/Dir3/SubDir1/Textures
mkdir -p Copy/Dir1 Copy/Dir2/SubDir1/SubSubDir1 Copy/Dir2/SubDir2 Copy/Dir3/SubDir1
Это - моделирование. После того как Вы выполнили его, и Вы уверены, что все корректно, удалите echo
и выполните его снова:
shopt -s globstar
for d in **/{Objects,Textures}; do
echo mv "$d" "Copy/${d##Original/}"
done
Объяснение:
**/
нуль соответствия или больше подкаталогов. **/{Objects,Textures}
до **/Objects **/Textures
. ${d##Original/}
означает, "удаляют строку Original/
из запуска $d
. Если вы хотите обновить деревья каталогов, используя другое местоположение, лучшим инструментом будет rsync
, а вторым, возможно, tar
. Написание сценария оболочки часто бывает излишним:
rsync -aP --ignore-existing Original/ Copy
Опции:
-a
говорит rsync
сохранять права владения, режимы и т. Д. -P
печатает информацию о прогрессе --ignore-existing
означает, что файлы, уже находящиеся в Copy
, не будут затронуты. /
после Original
указывается rsync
копировать содержимое Original
в Copy
вместо копирования самого Original
. Удалите Original
, когда закончите, или используйте опцию --remove-source-files
files, чтобы rsync
удаляли файлы, когда они закончили копировать их.
Вот пример того, как это может работать для вас. Обратите внимание, что этот сценарий должен выполняться на одном уровне с исходными и копируемыми каталогами, а также что он, вероятно, нуждается в адаптации к вашим реальным потребностям. Удачи.
#!/bin/bash
src="original"
dst="./copy"
function findLocation {
for i in `find $src/ -type d -name "$1"`; do
IFS='/' read -ra directories <<< "$i"
dirNum=${#directories[@]}
let "arrayNum=$dirNum-2"
arrs=()
for ((k=1 ; k<=$arrayNum; k++)); do
arrs+=("${directories[$k]}")
done
echo "===============================++++++++++++++++"
function join {
local IFS="$1"
shift
echo "$*"
}
constructDst=`join / ${arrs[@]}`
destination="$dst/$constructDst/"
if [ ! -d $destination ] ; then
mkdir -p $destination
echo "creating directory: $destination"
fi
if [ -d $i ]; then
echo "Moving $i to $destination"
mv $i -t $destination
fi
done
}
findLocation Textures
findLocation Objects
Вот один способ, которым Вам могло удаться переместить каталоги без подкаталогов.
Сначала включите рекурсивный globbing:
shopt -s globstar
Теперь Вы можете шарик рекурсивно с **
. Можно выключить его с shopt -u globstar
, но это будет от так или иначе следующего раза, когда Вы открываете оболочку.
Теперь в родительском каталоге обоих Copy
и Original
:
for d in Original/**/; do $(ls -lAq "$d" | grep -q '^d') || echo mv -vn -- "$d" Copy"${d/Original/}"; done
Удалить echo
после тестирования для фактического перемещения каталогов (и их содержание, конечно - mv
не имеет -r
флаг)
Давайте сделаем это более читаемым
shopt -s globstar
for d in Original/**/; do
$(ls -lAq "$d" | grep -q '^d') ||
echo mv -vn -- "$d" Copy"${d/Original/}"
done
Ожидайте, сделал я просто анализирую вывод ls
? Мм, да, я сделал. Но я думаю, что это в порядке (!), так как я думаю, что могу полагаться на непротиворечивость вывода в этом случае. Из каких символов имя файла содержит, вывод ls -l
на каталоге, где тот файл находится, начнется со строки, которая определяет ее тип и полномочия. В ls -l
все списки каталогов начинаются с a d
, например,
drwxrwxr-x 26 zanna zanna 4096 Oct 5 19:57 playground
Даже новые строки не портят это, поскольку они отображены как ?
(даже после передачи по каналу), если мы добавляем -q
.
$(ls -lAq "$d" | grep -q '^d')
проверки, что каталог имеет некоторые подкаталоги. Вместо того, чтобы собрать вывод из grep
, мы собираем статус выхода. Если команда успешна, мы ничего не делаем, но если она перестала работать, мы mv
каталог (использующий ||
или оператор, что означает, если команда прежде ||
сбои, сделайте тот после него).
Мы используем обработку строк для удаления Original
таким образом, каталоги копируются в правильные места в Copy
.
Вот результат:
$ tree
.
├── Copy
│ ├── Dir1
│ │ ├── Objects
│ │ └── Textures
│ ├── Dir2
│ │ ├── SubDir1
│ │ │ └── SubSubDir1
│ │ │ ├── Objects
│ │ │ └── Textures
│ │ └── SubDir2
│ │ ├── Objects
│ │ └── Textures
│ └── Dir3
│ ├── Objects
│ ├── SubDir1
│ │ ├── Objects
│ │ └── Textures
│ └── Textures
└── Original
├── Dir1
├── Dir2
│ ├── SubDir1
│ │ └── SubSubDir1
│ └── SubDir2
└── Dir3
└── SubDir1