将图像复制到特定文件夹

时间:2020-04-20 21:33:01

标签: python python-2.7 python-2.x

我是python的新手,我正在尝试构建一个小的脚本,该脚本可以从整个服务器上收集图像,我有一定的图像命名:

AMZ_1004.jpg
AMZ_1272.jpg
GOO_1.jpeg
GOO_2.png

我希望脚本浏览每个目录并将文件复制(而不移动)到AMZ&GOO

import shutil,os

goo_dst = '/home/usr2/Pictures/GOO'
amz_dst = '/home/usr2/Pictures/AMZ'
os.makedirs(goo_dst,exist_ok=1)
os.makedirs(amz_dst,exist_ok=1)
for root, dirs, files in os.walk('/'):
    for name in files:
        path = os.path.join(root, name)
        if name.startswith('GOO_') and (name.endswith('.jpg') or name.endswith('.jpeg') or name.endswith('.png')):
            shutil.copyfile(path, goo_dst)
        elif name.startswith('AMZ_') and name.endswith('.jpg'):
            shutil.copyfile(path, amz_dst)

脚本运行正常,有没有办法加快进程?

该脚本可以在Arch Linux上运行

5 个答案:

答案 0 :(得分:3)

您可以对脚本进行的最大优化不是在文件系统根目录上开始搜索。

此方法遍历了很多非文件的内容(例如/dev/proc文件夹)以及文件不太可能存在的系统文件夹。 (您真的不希望任何图片在/bin/usr/bin以下吗?)

尝试缩小实际搜索路径,例如Apache文件夹所在的/var/www

另一种优化可能根本不使用Python,而是直接使用Shell脚本:

#!/bin/sh
GOO_DST='/home/usr2/Pictures/GOO'
AMZ_DST='/home/usr2/Pictures/AMZ'

mkdir -p ${GOO_DST}
mkdir -p ${AMZ_DST}

find / -type f -name 'GOO_*.jpg' -o -name 'GOO_*.jpeg' -o -name 'GOO_*.png' -exec cp {} ${GOO_DST} \;

find / -type f -name 'AMZ_*.jpg' -exec cp {} ${AMZ_DST} \;

与手动遍历相比,find实用程序应该为您提供更快的结果。

如果您坚持使用Python,请至少移动path = os.path.join(root, name),以避免对不相关的文件(大多数文件)进行额外的工作。 这是一个很小的优化,但仍然可以提供帮助。

另一个选择是使用多线程来并行化搜索,但是您将需要手动确定每个线程将搜索文件系统的哪一部分。

如果2个线程经过同一文件夹,则将浪费更多时间。 另外,请注意,对该脚本进行多线程处理可能会导致其在运行时占用更多CPU。

Read here for more details

答案 1 :(得分:2)

如果需要python实现,则可以通过异步调用shutil来加快速度(应该允许shutil对不同文件并行运行)

// request 1
HomeController identity = 1249276649
MyClient identity = 1152488919

// request 2
HomeController identity = 41809453
MyClient identity = 213518354

答案 2 :(得分:0)

我认为您可以使用rsync而不是使用python脚本。 rsync代表“远程同步”,是一种远程和本地文件同步工具。它使用一种算法,通过仅移动已更改的文件部分来最大程度地减少复制的数据量。例如您的情况;

rsync -a "$PWD" --include='*/' --include='GOO_*.jpg' --include='GOO_*.jpeg' --include='GOO_*.png' --exclude='*' /home/usr2/Pictures/GOO/

rsync -a "$PWD" --include='*/' --include='AMZ_*.jpg' --exclude='*' /home/usr2/Pictures/AMZ/

或者您也可以使用简单的方式;

rsync $(pwd)/GOO_*.{jpg,jpeg,png} /home/usr2/Pictures/GOO/

rsync $(pwd)/AMZ_*.jpg /home/usr2/Pictures/AMZ/

最后,将其与mkdir (如果您还需要创建路径)组合起来;

#!/bin/bash

GOO_PATH='/home/usr2/Pictures/GOO/'
AMZ_PATH='/home/usr2/Pictures/AMZ/'

mkdir -p ${GOO_PATH} && rsync $(pwd)/GOO_*.{jpg,jpeg,png} ${GOO_PATH}
mkdir -p ${AMZ_PATH} && rsync $(pwd)/AMZ_*.jpg ${AMZ_PATH}

答案 3 :(得分:0)

由于您在Linux上使用python2.7,因此可以使用以下优化:

  • 使用内置的系统cp
  • 为副本分页文件
  • TODO:将调用批量处理到find_files迭代器

我让您为它们计时,看看它们是否有帮助。

由于每个副本都在争用磁盘,因此我不希望并行化副本会有很大帮助。

import shutil, os

goo_dst = '/home/usr2/Pictures/GOO'
amz_dst = '/home/usr2/Pictures/AMZ'


def find_files(path='/'):
    for root, dirs, files in os.walk(path):
        for name in files:
            path = os.path.join(root, name)
            if name.startswith('GOO_') and (name.endswith('.jpg') or name.endswith('.jpeg') or name.endswith('.png')):
                yield(path, goo_dst)
            elif name.startswith('AMZ_') and name.endswith('.jpg'):
                yield(path, amz_dst)

def my_cp(dst, files):
    # we use array form to avoid problems with file paths containing spaces
    return subprocess.call(["cp"] + files, shell=False)

def main:
    os.makedirs(goo_dst, exist_ok=1)
    os.makedirs(amz_dst, exist_ok=1)

    files = {goo_dst: [],
             amz_dst: []}
    base_path = '/' # limit this if possible, www/data perhaps?
    min_copy = 50 # tune for your needs
    for path, dest in find_files(base_path):
        files[dest].append(path)
        if len(files[dest]) > min_copy:
            my_cp(dest, files[dest])
            files[dest] = []
    # clean up any remaining files
    for dest, paths in files.iter_items(): 
        if paths:
            my_cp(paths, dest)
main()

答案 4 :(得分:-2)

您可以尝试使用opencv读取/复制现有文件,然后在指定目录中创建新文件,如下所示:

image = cv2.imread('C:/original image path')
cv2.imwrite('C:/new image path', image)