копировать файлы вместе с их (последними) папками - PullRequest
0 голосов
/ 31 марта 2012

Я могу найти и скопировать все файлы в заданную папку с помощью команды find -exec. Но мне нужно найти и скопировать все файлы по заданному пути вместе с папкой, в которой он был сохранен. Итак ....

/path/to/file/is/abc.txt
/another/file/is/here/xyz.txt

Мне нужно скопировать эти 2 файла вместе с их путем к следующей папке:

/ MySQL / данные /

Новая структура файла будет выглядеть следующим образом ...

/mysql/data/is/abc.txt
/mysql/data/here/xyz.txt

Это сделано для того, чтобы избежать возможной перезаписи повторяющихся имен файлов. Последние имена папок будут уникальными, но имена файлов могут совпадать.

Каков наилучший способ сделать это?

Ответы [ 4 ]

3 голосов
/ 31 марта 2012

Вот краткий сценарий с довольно длинным объяснением *, сопровождающим его.

for oldpath in $your_file_list; do
    mv ${oldpath} /mysql/data${oldpath##$(dirname $(dirname $oldpath))}
done

Как это работает

  • Утилита dirname удаляет все до и включая последнюю косую черту (/) из пути.Двойной вызов приведет к удалению всего, вплоть до последней косой черты.

  • Идиома $(command with params) выполняет command с параметрами with params и возвращает выходные данные.

  • Идиома ${var##prefix} возвращает содержимое переменной var с удалением prefix.

Шаг за шагоманализ

Если oldpath равно /path/to/file/is/abc.txt, то:

  • dirname $oldpath равно /path/to/file/is
  • dirname $(dirname $oldpath) равно /path/to/file
  • ${oldpath##$(dirname $(dirname $oldpath))} - это /is/abc.txt

, который является частью исходного пути, который будет добавлен к новому пути.


* Элегантное ( прил. ) программное обеспечение: любое программное обеспечение, реализующее алгоритм, чье объяснение длиннее, чем сама реализация.

1 голос
/ 31 марта 2012

Это может сработать для вас:

a=/mysql/data
sed 's|.*\(/[^/]*/[^/]*\)|mv -v & '"$a"'\1|' file 
mv -v /path/to/file/is/abc.txt /mysql/data/is/abc.txt
mv -v /another/file/is/here/xyz.txt /mysql/data/here/xyz.txt

Изучить вывод и, если все в порядке, запустить:

sed 's|.*\(/[^/]*/[^/]*\)|mv -v & '"$a"'\1|' file | bash
1 голос
/ 31 марта 2012

Вам нужно будет написать сценарий / запрограммировать это решение.

Пример быстрого Python:

import os
import shutils
src_root = '/path/to/walk/'
dst_root = '/mysql/data/'
for root,dirs,files in os.walk(src_root):
    for file in files:
        dst_path = os.path.split(root)[1]
        dst_path = os.path.join(dst_root, dst_path)
        os.makedirs(dst_path)
        src = os.path.join(root,i file)
        dst = os.path.join(dst_path, file)
        shutils.copyfile(srd, dst)
0 голосов
/ 01 апреля 2012

Если вы хотите сначала скопировать файл, вам нужно создать для него каталог. Вы можете сделать это с помощью одной команды find, но я не уверен в эффективности этого решения?

#!/bin/bash
# $1 - destination

find $1 -type f -exec bash -c '
  dest="$2";                            # $2 is second argument passed to the script
  dir=$(basename $(dirname $1));        
  mkdir $dest/$dir 2>/dev/null;        
  cp $1 "$dest/$dir/";                  
' -- {} $2 \;                           # {} = $1 in bash '..' and $2=$2

использование: ./copy copy_from copy_to

редактировать: это выглядит лучше:

#!/bin/bash

dest=$2
from=$1

# copy_file from dest
copy_file() {
 dir=$(basename $(dirname $from))
 mkdir $dest/$dir
 cp $from $dest/$dir
}

find $from -type f | while read file; do copy_file $file $dest; done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...