Всем привет, я снова.
Когда я вчера ходил в туалет, у меня был каприз, когда втыкаешь usb, можно ли автоматически запускать программу на usb. Я проверил его и обнаружил, что он доступен только в Windows, и вы также можете найти его (поиск по ключевому слову usb autorun). Однако, если я хочу, например, когда USB подключен, автоматически копировать важные файлы с USB на локальный или автоматически загружать их на сервер в фоновом режиме, мне нужна помощь специального программного обеспечения.
Поэтому я подумал про себя, могу ли я написать программу на питоне и позволить ей работать в фоновом режиме. Всякий раз, когда вставляется U-диск, он автоматически копирует важные файлы.
Как определить, вставлен диск U или нет?
Сначала мы открываем компьютерный терминал, входим в каталог / Volumes, вставляем диск U в это время, мы можем обнаружить, что он смонтирован в этом каталоге, то есть нам нужно только сканировать этот каталог в фиксированное время, когда в этом каталоге есть новая папка Когда она появляется, скорее всего, был вставлен USB-накопитель.
Мой дизайн таков, используйте функцию time.sleep(3), чтобы программа продолжала работать, и проверяйте каталог /Volumes/ каждые три секунды.Если папок больше, скопируйте их в другую папку.
# encoding=utf-8
from time import sleep
import os, shutil
usb_path = "/Volumes/"
content = os.listdir(usb_path) # os.listdir(路径)返回路径下所有文件以及文件夹的名称
while True:
new_content = os.listdir(usb_path) #每隔三秒扫描一次/Volumes/
if new_content != content: # 如果发现异常,即多出一个文件夹,则退出
break;
sleep(3)
x = [item for item in new_content if item not in content]
# 找到那个新文件夹,返回包括新文件夹string类型名称的列表,这个表达方法很pythonic
shutil.copytree(os.path.join(usb_path, x[0]), '/Users/home/usb_copy')
# shutil.copytree 把目录下所有东西一股脑复制进/Users/home/usb_copy,
# 放进了自己的home目录下
Как видно из названия, мы действительно используем только 10 строк (на самом деле 11 строк, составим целое :) Доделал этот "вирус". Мы можем обнаружить каталог на USB, все лежащие в домашнем каталоге после вставки в течение полминуты.
Как копировать файлы выборочно?
Мы только что написали очень простой скрипт, чтобы проверить осуществимость этой идеи, но есть еще проблемы. Причина, по которой я могу быстро скопировать все файлы на диск U только сейчас, заключается в том, что на диске U всего два или три файла, а размер не превышает 15 МБ. Если на целевом USB есть много фильмов, музыки, файлов, которые нам не нужны, наша программа должна иметь возможность пропустить их и просто выбрать некоторые важные файлы, такие как .docx или .ppt, или просто скопировать недавно измененные файлы, или исключить все файлы размером более 5M. Можем ли мы сделать это с помощью python? Конечно!
os.walk рекурсивно все файлы в папке
Метод Python os.walk()Здесь я помещаю учебник от кого-то другого. Все это понимают, короче, я, наверное, понимаю эту вещь.
Возьмем пример.
Я создал папку testwalk в каталоге с тремя файлами file123.txt и тремя папками folder123, среди которых в папке1 есть файлы file4.txt и folder4
➜ testwalk touch file1.txt file2.txt file3.txt
➜ testwalk mkdir folder1 folder2 folder3
➜ testwalk cd folder1
➜ folder1 touch file4.txt && mkdir folder4
➜ folder1 cd ..
# 上面创建了这些文件以及文件夹,你也可以在图形界面上创建
# tree 是个很好玩的命令,可以直观地显示文件路径
➜ testwalk tree ./
testwalk/
├── file1.txt
├── file2.txt
├── file3.txt
├── folder1
│ ├── file4.txt
│ └── folder4
├── folder2
└── folder3
4 directories, 4 files
Теперь давайте проверим это
import os
for root, dirs, files in os.walk("./testwalk/"):
for name in files:
print(os.path.join(root, name))
for name in dirs:
print(os.path.join(root, name))
-----------------------------------------------------------------------------
运行结果:
./testwalk/folder1/file4.txt
./testwalk/folder1/folder4
./testwalk/file2.txt
./testwalk/file3.txt
./testwalk/file1.txt
./testwalk/folder2
./testwalk/folder3
./testwalk/folder1
root хранит текущее местоположение, он будет использовать все папки в ./testwalk/ в качестве корневого каталога и искать вниз
for root, dirs, files in os.walk("./testwalk/", topdown=False):
print(root)
./testwalk/folder2
./testwalk/folder3
./testwalk/folder1/folder4
./testwalk/folder1
./testwalk/
Просмотр каталогов по отдельности
for root, dirs, files in os.walk("./testwalk/"):
for name in dirs:
print(os.path.join(root, name))
./testwalk/folder2
./testwalk/folder3
./testwalk/folder1
./testwalk/folder1/folder4
Просмотр файлов по отдельности
for root, dirs, files in os.walk("./testwalk/", topdown=False):
for name in files:
print(os.path.join(root, name))
./testwalk/file2.txt
./testwalk/file3.txt
./testwalk/file1.txt
./testwalk/folder1/file4.txt
Ну и нам теперь нужно рекурсивно папку usb найти все файлы, проверить размер, если он меньше, например 3М, скопировать в хоум, если больше его, сбросить.
модуль шутил
import shutil
>>> help(shutil)
>>> dir(shutil)
['Error', 'ExecError', 'SpecialFileError', 'WindowsError',
'_ARCHIVE_FORMATS', '_BZ2_SUPPORTED', '_ZLIB_SUPPORTED', '__all__',
'__builtins__', '__doc__', '__file__', '__name__', '__package__',
'_basename', '_call_external_zip', '_destinsrc', '_get_gid', '_get_uid',
'_make_tarball', '_make_zipfile', '_samefile', 'abspath',
'collections', 'copy', 'copy2', 'copyfile', 'copyfileobj',
'copymode', 'copystat', 'copytree', 'errno', 'fnmatch',
'get_archive_formats', 'getgrnam', 'getpwnam', 'ignore_patterns',
'make_archive', 'move', 'os', 'register_archive_format', 'rmtree',
'stat', 'sys', 'unregister_archive_format']
Ну, я не понимаю, я все еще должен прочитатьофициальная документация.
Теперь давайте возьмем только что папку в качестве примера.Если мы хотим скопировать файл1.txt в папку2:
>>> shutil.copy2('./file1.txt', './folder2')
------------------------------------------------我是分割线-----------
➜ folder2 ls
file1.txt
В Shutil используется множество инструментов, которые не будут здесь подробно описываться.
os.path.getsize() определяет размер
os.path.getsize(имя файла) возвращает значение в байтах, если оно используется для просмотра размера файла, нам нужно вручную написать функцию для преобразования его в удобный для чтения вид.
movie = /Users/home/somemovie.rmvb
def convert_bytes(num):
# this function will convert bytes to MB.... GB... etc
for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
if num < 1024.0:
return "%3.1f %s" % (num, x)
num /= 1024.0
def getDocSize(path):
try:
size = os.path.getsize(path)
return size
except Exception as err:
print(err)
print(convert_bytes(getDocSize(movie)))
结果:
1.3 GB
[Finished in 0.1s]
Здесь нам нужно только выбрать размер файла меньше 3М, 3М = 3 * 1024кБ = 3 * 1024*1024байт
for root, dirs, files in os.walk(os.path.join(usb_path, x[0])): #MyUSB location
for name in files:
file = os.path.join(root, name)
if os.path.getsize(file) < 3*1024*1024:
shutil.copy2(file, target_folder)
Объедините Shutil.copy2, чтобы скопировать файлы выбранного размера в нашу целевую папку.
Как указать тип файла
Здесь нам нужны регулярные выражения, чтобы помочь нам.
Контента регулярных выражений много, и целая глава используется в «Программировании ядра Python», поэтому мы не будем вдаваться в нее. Ниже приведен официальный документ, вы можете взглянуть, если вам интересно.
7.2. re - Regular expression operations - Python 2.7.14 documentationТаким образом, мы разрешаем копирование указанного суффикса файла и указанного размера файла в наш целевой файл:
не забудьте импортировать повторно
import re
...
regex_filename = re.compile('(.*zip$)|(.*rar$)|(.*docx$)|(.*ppt$)|(.*xls$)')
for root, dirs, files in os.walk(os.path.join(usb_path, x[0])): #MyUSB location
for name in files:
file = os.path.join(root, name)
if regex_filename.match(file) and os.path.getsize(file) < 1024*1024:
shutil.copy2(file, target_folder)
Типы файлов могут быть лучше указаны с помощью более сложных регулярных выражений.
Фильтрация файлов по времени модификации
>>> from os.path import *
>>> help(getmtime)
getmtime(filename)
Return the last modification time of a file, reported by os.stat().
>>> help(getctime)
getctime(filename)
Return the metadata change time of a file, reported by os.stat().
В это время я создал файл под названием NewFile в каталоге
>>> getctime("newfile")
1522746383.716875
# 我们可以看到返回的time是从某个时间到现在的秒数,如需阅读,我们需要time.ctime来转换
>>> import time
>>> time.ctime(1522746383.716875)
'Tue Apr 3 17:06:23 2018' # 这就是刚才创建的时间啦
>>> help(time.ctime)ctime(...) # 查看文档
ctime(seconds) -> string
Convert a time in seconds since the Epoch to a string in local time.
This is equivalent to asctime(localtime(seconds)). When the time tuple is
not present, current time as returned by localtime() is used.
Короче говоря, фильтрация времени модификации каждого файла позволяет копировать только те файлы, которые были изменены или добавлены недавно, либо за определенный период, что полезно в определенных ситуациях.
Суммировать
На самом деле название просто для привлечения всеобщего внимания Это небольшая программа, и это не вирус. Я хотел бы использовать этот пример, чтобы продемонстрировать мощные возможности Python для обработки файлов и пробудить у всех энтузиазм к обучению. Все вышеперечисленные реализации основаны на macos, Linux должен быть таким же, а Windows может быть успешным с небольшой модификацией.
Если вам это нравится, ставьте лайк и подписывайтесь.