С Bash, Как я нахожу все каталоги с двумя каталогами и перемещаю их в скопированную древовидную структуру?

Позволяет говорят, что у меня есть следующая структура дерева каталогов:

./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

Вещи заметить:

  • Не все каталоги в Исходном Каталоге имеет каталоги Objects и Textures
  • Объекты и Каталоги Структур перемещены и не скопированы
  • Также каталоги Original и Copy находятся в том же каталоге, и это - то, где команду/функцию нужно назвать

Используйте эту команду для создания стартовой структуры:

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
2
задан 5 October 2017 в 20:43

4 ответа

Это - моделирование. После того как Вы выполнили его, и Вы уверены, что все корректно, удалите echo и выполните его снова:

shopt -s globstar
for d in **/{Objects,Textures}; do
    echo mv "$d" "Copy/${d##Original/}"
done

Объяснение:

  • Включение опции Bash "globstar" делает шарик **/ нуль соответствия или больше подкаталогов.
  • Bash расширяется **/{Objects,Textures} до **/Objects **/Textures.
  • ${d##Original/} означает, "удаляют строку Original/ из запуска $d.
4
ответ дан 2 December 2019 в 01:36

Если вы хотите обновить деревья каталогов, используя другое местоположение, лучшим инструментом будет 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 удаляли файлы, когда они закончили копировать их.

2
ответ дан 2 December 2019 в 01:36

Вот пример того, как это может работать для вас. Обратите внимание, что этот сценарий должен выполняться на одном уровне с исходными и копируемыми каталогами, а также что он, вероятно, нуждается в адаптации к вашим реальным потребностям. Удачи.

#!/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
0
ответ дан 2 December 2019 в 01:36

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

Сначала включите рекурсивный 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
1
ответ дан 2 December 2019 в 01:36

Другие вопросы по тегам:

Похожие вопросы: