我是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上运行
答案 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。
答案 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,因此可以使用以下优化:
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)