Pull to refresh

Comments 59

UFO just landed and posted this here
конечно можно и даже нужно :) спасибо за дополнения, учту в сл. раз или может даже перепишу это, чтобы не было кашей. да, в данный момент вообще не учитывается, что пользователь мог перенести Загрузки в другое место.
Тоже немного побуду занудой: наверное, все-таки не usermane («грива пользователя»), а username («имя пользователя»). :)
Кто-то уже отписал кучу сообщений об ошибке в личку
ошибки в основном грамматические, по крайней мере в личке инфа о них
Занудой надо быть последовательно: есть ещё относительно распространённые ОС вроде Free/Net/Open/DraginFlyBSD (пожалуй, примерно в порядке убывания распространённости/популярности), для которых код бы вполне работал, если бы не линуксовиндовый шовинизм автора

P.S. кажется, я не учёл, что если последовать вашим рекомендациям, он, видимо, и заработает и там. Тем они (рекомендации) ещё ценнее
ну на Windows и Linux работает. а на др. системы я даже не ориентировался. потому что не надо.
UFO just landed and posted this here
вы полагаете, что только я после установки системы оставляю папку с загрузками там, где она стоит по-умолчанию? :) а все иные пользователи сразу же начинают её перемещать в другие места? говоря многие вы оперируете достаточно размытыми понятиями. например, число пользователей Office 365 (а следовательно пользователей Windows) достигло 135 млн человек. вы можете назвать какой процент из этих людей переносит папку загрузок после установки системы?
Вы просто делаете не универсальное решение и вам на это пытаются указать, а вы старательно отмазываетесь. Хотите делать что то — старайтесь делать это хорошо.

Это не попытка указать на ошибки, а попытка умничать. В этом случае человек пытается выдать свой опыт за то, что делают другие. Чего делать не стоит. Обратите внимание на нормальные указания на ошибки и мою реакцию — увидите разницу. Я с радостью воспринимаю и принимаю критику, но только если это критика, а не выпендреж.

UFO just landed and posted this here

Ну так у меня и прописан вариант для русской версии установки. Я не заявлял нигде, что этот код будет работать на всех локализациях Linux. Вы читайте внимательно — в первую очередь я делал это для себя. У меня русская версия Archlinux, Windows в виртуалке. На основании этого и делал. Зачем в таком случае требовать универсальности? Если её изначально не заявлено на данный момент.

UFO just landed and posted this here
UFO just landed and posted this here
Тонкость в том, что совсем не намеренная :) За комментарий спасибо!
некому линейкой по рукам бить, я одинок и познаю Python самостоятельно :) потому мне и нужна критика, разбор кода, указание на ошибки. на мой взгляд, это лучше, чем писание «в стол».
UFO just landed and posted this here

Ну так я пока что и не хороший программист, я только учусь :)

Да простит меня комьюнити за мое мнение, но, еще раз ИМХО, статьи с подобным уровнем подготовки а-ля курсач 3-го курса первого полугодия способствуют общему понижению уровня ресурса.
Особенно, если учесть использование жутких антипаттернов.
Я тоже сделаю небольшое замечание по словарям. Постоянное повторение одного и того же куска кода, или значения в словаре, или еще что повторяющееся должно сразу наталкивать на мысль, что здесь что-то не так, и наверняка можно оптимизировать более доступно.
Например все эти 4 словаря можно преобразовать к одному словарю типа:
folders = {
            "Видео/": [".3gp", ".avi", ".flv", ".m4v", ".mkv", ".mov", ".mp4", ".wmv", ".webm"],
            "Музыка/": [".mp3", ".aac", ".flac", ".mpc", ".wma", ".wav"],
            "Изображения/": [".raw", ".jpg", ".tiff", ".psd", ".bmp", ".gif", ".png", ".jp2", ".jpeg"],
            "Документы/": [".doc", ".docx", ".txt", ".rtf", ".pdf", ".fb2", ".djvu", ".xls", ".xlsx", ".ppt", ".pptx", ".mdb", ".accdb", ".rar", ".zip", ".7z"]
}

Тогда потом получится один маленький цикл на 4 итерации. А Наличие расширения в списке можно проверять оператором in.
Например что-то типа такого:
ext = #тут вы получаете расширение файла
for folder, ext_list in folders.items():
    if ext in ext_list:
        #ваш код
Спасибо за комментарии. Учту в будущем.
Здесь точка в каждом из значений не менее лишняя, чем повторение имени папки
Возможно. Способ получения расширения файлов и работа с ними оставлена автору. Я просто показал как можно реорганизовать словарь для более короткого определения и более удобной работы с ним. Так же замечу, что мой вариант не является единственно правильным, а просто один из вариантов, который как по мне в первую очередь бросается в голову, глядя на словари автора. Каждый может построить свои структуры, как кому по нраву.
или можно «перевернуть» folders и использовать в авторском варианте:
extension_folder = {ext: folder for folder, ext in folders.items()}
ext = ...
folder = extension_folder.get(ext)
...

C:/Users/имяпользователя/Downloads/
В разных версиях Windows эта папка находится в других местах. И это по-умолчанию, так как её можно переместить или переопределить, опять же в зависимости от версии Windows/

В версиях с 7 до 10 папка загрузок всегда находится по одному пути. Проверено уже. А вот возможность переноса это да — я это не учитывал намеренно пока что.

Это только если:
  1. Windows установлена на диске C:
  2. Профиль пользователя находится в C:/Users/имяпользователя/
  3. пользователь никуда не переместил папку загрузок
  4. пользователь не переопределил путь к папке загрузок

Не многовато ли оговорок для того, чтобы ваши слова соответствовали истине?
А в домене так вообще профили пользователей могут быть перемещаемыми…
А где по-вашему они (перемещаемые профили) хранятся локально?
Ну вот у вас где папка Загрузки находится?
Кстати, у меня точно такой же адрес :)

Но это явно не стандартный путь. Вариант, при котором папка перемещена пользователем я пока что не рассматривал даже.

А зря. Плюс одна ошибка в статье. У меня вот папки загрузки тоже расположены не по стандартным путям ни в винде, ни в линуксе.


И домашняя папка пользователя целиком тоже может быть перемещена как минимум в линуксе.

Об этом в тексте статьи я написал уже.
А что произойдёт, если в папку для перемещения прав на запись не будет или самой папки не будет или она совпадёт с исходной или файл будет занят другим процессом на момент перемещения, но не будет занят на момент завершения (при включённом удалении)? А с симлинками и вложенными папками что будет? Если места не хватит для переноса файлов, они все в конце удалятся?
А почему типы файлов не хранить в отдельном конфиге?
И собственно пути до целевых директорий.
Надо сделать примерно то же, но с целым диском (500 Гб, ntfs). На нем после восстановления данных образовалось около четырехсот папок до тысячи файлов в каждой. Надо отсортировать их по расширениям и положить в соответствующие папки. Система основана на Archlinux, если что.
Есть ли несложный способ для выполнения этой задачи?
Примерно так:
shell>: export OUTDIR=~/tmp/mp3; mkdir $OUTDIR; find /mnt/disk/ -type f -name "*.mp3" -print -exec cp {} $OUTDIR \;

Данная команда найдет все mp3-файлы в каталоге /mnt/disk (куда примонтирован диск) и скопирует их в созданный каталог tmp/mp3 в домашнем каталоге пользователя.
Если я правильно понял задачу.
Если нужно переместить, то «cp» меняется на «mv», но сперва лучше попробовать с копированием =)

Это решение в лоб, но по хорошему надо сразу автоматом анализировать типы файлов, создавать соответственно каталоги и копировать туда.
Спасибо, Вы правильно поняли задачу. Только желательно сразу перемещать файлы в соответствующие папки на том же диске, ибо под линукс отрезано не так много места на диске.
Если бы ещё и папки автоматом создавались… ))) Но это не принципиально.
лучше объединять пути через
os.path.join(root, dir)

Спрашивать у пользователя в тексте ввод директории не очень для него удобно. Легко допустить ошибку при вводе. Навреное лучше подключиться к одной из гуи библиотек и показать нормальное окно выбора директории. что-то типа PyWx или PyQt подойдет, хотя конечно подключать их для одного окна это жуткий оверкилл ( хотя кого я обманываю сейчас весь софт так пишется ).
UFO just landed and posted this here

Код использующий pathlib очень плохо читается и слишком неявный в отличии от os.path.join.

UFO just landed and posted this here

В одном открытом проекте встречал:


path = long_var_name_a / long_var_name_b /
    long_var_name_c / long_var_name_d / long_var_name_e

Вместо:


path = os.path.join(
    long_var_name_a,
    long_var_name_b,
    long_var_name_c,
    long_var_name_d,
    long_var_name_e,
)

Форматирование это только одна проблема. Если не держать в голове, что в переменных пути, придётся отматывать контекст назад, пытаясь понять, что же здесь на что делится. С join такой проблемы нет, он задаёт контекст сразу же.

Да можно же использовать tkinter, который на windows к тому же идет в комплекте с питоном. Системный диалог выбор директории, реализуется в одну строчку (кроме импорта конечно же)

У меня Archlinux, потому я ориентировался в первую очередь на Linux-based дистрибутивы.

У арча tkinter тоже никто не отбирал.

Одной строчкой на питоне. Где-то уже это слышал…
Приступил к изменению программы с основой на ваши комментарии :-)
Как то так
import os
import shutil
import json

from tkinter import (
    BOTTOM,
    Button,
    E,
    Frame,
    Label,
    StringVar,
    Tk,
    W,
    X,
    filedialog,
    mainloop,
)
from pathlib import Path, PurePath


def browse_button():
    global folder_path
    filename = filedialog.askdirectory()
    folder_path.set(filename)


def clean_button():
    global folder_path
    os_path = Path(folder_path.get())
    with open("config.json", "r", encoding="utf8") as config_file:
        folders = json.load(config_file)
    for k in folders.keys():
        for f in os.listdir(os_path):
            print(PurePath(f).suffix, PurePath(f).suffix.lstrip("."))
            if (
                len(PurePath(f).suffix) > 1
                and PurePath(f).suffix.lstrip(".") in folders[k]
            ):
                try:
                    shutil.move(Path(f"{os_path}\\{f}"), Path(f"{os_path}\\{k}\\{f}"))
                except Exception as e:
                    print(e.args)
                    os.makedirs(Path(f"{os_path}\\{k}\\"))
                    shutil.move(Path(f"{os_path}\\{f}"), Path(f"{os_path}\\{k}\\{f}"))


root = Tk()
root.title("Выбор каталога Загрузок")  # Add a title
root.minsize(400, 20)

folder_path = StringVar()

main_frame = Frame(root)
main_frame.pack(fill=X, side=BOTTOM)

path_label = Label(main_frame, textvariable=folder_path)
clean_button = Button(main_frame, text="Очистить", command=clean_button)
browse_button = Button(main_frame, text="Выбрать", command=browse_button)

main_frame.columnconfigure(0, weight=5)
main_frame.columnconfigure(1, weight=1)
main_frame.columnconfigure(2, weight=1)

path_label.grid(row=0, column=0, sticky=W + E)
clean_button.grid(row=0, column=1, sticky=W + E)
browse_button.grid(row=0, column=2, sticky=W + E)

mainloop()



{
	"Видео": [
		"3gp",
		"avi",
		"flv",
		"m4v",
		"mkv",
		"mov",
		"mp4",
		"wmv",
		"webm"
	],
	"Музыка": [
		"mp3",
		"aac",
		"flac",
		"mpc",
		"wma",
		"wav"
	],
	"Изображения": [
		"raw",
		"jpg",
		"tiff",
		"psd",
		"bmp",
		"gif",
		"png",
		"jp2",
		"jpeg"
	],
	"Документы": [
		"doc",
		"docx",
		"txt",
		"rtf",
		"pdf",
		"fb2",
		"djvu",
		"xls",
		"xlsx",
		"ppt",
		"pptx",
		"mdb",
		"accdb"
	],
	"Архивы": [
		"rar",
		"zip",
		"7z",
		"gz",
		"iso"
	],
	"Программы": [
		"exe",
		"msi",
		"apk"
	],
	"Торренты": [
		"torrent"
	]
}

Sign up to leave a comment.

Articles