Как мне переместить тысячи файлов из списка?

Итак, у меня есть список файлов в текстовом файле. Я считаю, что это около 100000 файлов.

Файлы в указанном списке распределены по многим каталогам, имеют разные размеры, имена файлов, расширения, возраст и т. Д.

Я пытаюсь найти способ переместить эти файлы и только эти на другой диск.

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

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

Ниже приведен пример некоторых строк в текстовом файле с именами исходных файлов:

media/dave/xdd/cruzer/F#(NTFS 1)/Raw Files/Portable Network Graphic file/3601-3900/FILE3776.PNG/Windows/winsxs/amd64_microsoft-windows-o..disc-style-memories_31bf3856ad364e35_6.1.7600.16385_none_51190840a935f980/Title_mainImage-mask.png
media/dave/xdd/d1/other/hd1/Program Files/DVD Maker/Shared/DvdStyles/Memories/Title_content-background.png

Я пытался использовать

rsync -av `cat /sourcefile.txt` /media/destinationhdd

который жалуется, что есть слишком много аргументов.

Также

rsync -a --files-from=/sourcefile.txt / /media/destinationhdd

а также

cat /sourcefile.txt | xargs -n 200 rsync -av % /media/destinationhdd

Тем не менее, это просто пытается скопировать мой корневой каталог в место назначения.


Как мне просто скопировать конкретные файлы, которые я хочу?

3 ответа

Решение

Вот небольшой скрипт для вас:

#!/bin/sh

while read line
do
    DIR=`dirname "$line"`
    mkdir -p "$2/$DIR"
    mv "$line" "$2/$DIR"
done < $1

Использование (если вы сохранили скрипт как script.sh и сделал его исполняемым с chmod +x script.sh):

./script.sh input.txt output_directory

Это переместит все файлы, перечисленные в input.txt в output_directoryиспользуя их исходные пути, например, для input.txt имеет следующий список:

test.txt
dir1/test.txt
Another Test/something_else.txt

Файлы будут перемещены в:

output_directory/test.txt
output_directory/dir1/test.txt
output_directory/Another Test/something_else.txt

Я провел некоторое тестирование, прежде чем опубликовать этот ответ, но, пожалуйста, убедитесь, что вы сначала попробовали его на меньшем образце, чтобы убедиться, что он работает как положено!

Следующий скрипт сначала копирует структуру каталогов из источника, затем файлы из вашего списка в соответствующие папки. Линия if not line in ["", "\n"] Предотвращает ошибки в случае, если список файлов содержит пустые строки.

#!/usr/bin/env python

import os
import shutil

source = "/path/to/source"; target = "/path/to/target"; filelist = "/path/to/filelist.txt"

for root, dirs, files in os.walk(source):
    for dr in dirs:
        dr = root+"/"+dr
        destdir = dr.replace(source, target)
        if not os.path.exists(destdir):
            os.makedirs(destdir)

with open(filelist) as lines:
    src = lines.readlines()

for line in src:
    if not line in ["", "\n"]:
        shutil.copyfile(line.replace("\n", ""),
            line.replace("\n", "").replace(source, target))

Как пользоваться

  • Скопируйте скрипт в пустой файл, сохраните его как move.py
  • Добавьте соответствующие пути в главном разделе
  • Запустите его:

    python /path/to/move.py
    

Вы можете сделать это с помощью xargs довольно легко.

mkdir /newroot/
<filenames.txt xargs -I% bash -c 'mkdir -p /newroot/$(dirname "%" && cp "%" "/newroot/%"'

Сложность в том, чтобы убедиться, что новая структура каталогов существует. Для этого мы используем dirname чтобы получить имена каталогов, mkdir -p построить их и, наконец, cp (или же mv) копировать / перемещать от одного к другому. Я оставил его в режиме копирования, чтобы вы могли проверить.

Я бы предложил проверить это find /newroot/ -type f | wc -l а также wc -l filenames.txt оба дают вам тот же номер потом.

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