Как мне переместить тысячи файлов из списка?
Итак, у меня есть список файлов в текстовом файле. Я считаю, что это около 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
оба дают вам тот же номер потом.