Linux(含UOS)可用带界面调整文件所有者和权限的软件,基于Python

面向Linux普通用户,解决不用命令调整文件或文件夹权限的问题。让AI顺手写的,界面未优化,反正可以用。


两个功能:

    一是修改指定的文件夹(或文件)的所有者为特定用户。解决文件带锁标志的问题。当修改为当前用户时,就没锁了。修改所有者为root时,普通用户看起来就是有锁的。
    二是授予特定文件可执行权限,就是运行某个文件能当成程序运行。
因为部分操作需要使用sudo命令提权才能执行,当遇到此类情况时,会弹出对话框提示输出当前用户的登录密码。软件单次运行期间,正确输入密码后,后续操作不需要重复输入密码。软件退出时自动销毁密码等信息,不保持数据。

python源码如下(缺少TK库的,自己去百度安装方法):

#!/usr/bin/env python3
import os
import stat
import tkinter as tk
from tkinter import filedialog, scrolledtext, messagebox, simpledialog
import platform
import subprocess
import logging
from shlex import quote

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')


class FilePermissionManager:
    def __init__(self, root):
        self.root = root
        self.root.title("文件/文件夹权限管理")

        if platform.system() == "Linux":
            self.root.geometry("510x470")
        else:
            self.root.geometry("500x400")

        try:
            self.current_user = os.getlogin()
        except OSError:
            self.current_user = os.environ.get('USER', 'unknown')
            logging.warning("无法获取登录用户,使用环境变量 USER")

        # 缓存密码
        self.sudo_password = None

        self.main_frame = tk.Frame(root)
        self.main_frame.pack(fill="both", expand=True, padx=10, pady=10)

        self.left_frame = tk.Frame(self.main_frame)
        self.left_frame.pack(side="left", fill="y")

        self.result_frame = tk.Frame(self.main_frame)
        self.result_frame.pack(side="right", fill="both", expand=True)

        tk.Label(self.left_frame, text=f"当前用户: {self.current_user}").pack(pady=5)

        tk.Label(self.left_frame, text="修改所有者权限").pack(pady=(0, 5))
        self.owner_path_entry = tk.Entry(self.left_frame, width=30)
        self.owner_path_entry.pack(pady=5)

        self.button_frame = tk.Frame(self.left_frame)
        self.button_frame.pack(pady=5)
        tk.Button(self.button_frame, text="选择文件夹", command=self.select_owner_path).pack(side="left", padx=5)
        tk.Button(self.button_frame, text="选择文件", command=self.select_owner_files).pack(side="left", padx=5)

        tk.Button(self.left_frame, text="改为 root", command=self.change_owner_to_root).pack(pady=5)
        tk.Button(self.left_frame, text="改为当前用户", command=self.change_owner_to_current).pack(pady=5)

        tk.Label(self.left_frame, text="文件执行权限").pack(pady=(20, 5))
        self.exec_path_entry = tk.Entry(self.left_frame, width=30)
        self.exec_path_entry.pack(pady=5)
        tk.Button(self.left_frame, text="选择文件", command=self.select_exec_file).pack(pady=5)
        tk.Button(self.left_frame, text="授予权限", command=self.make_executable).pack(pady=5)
        tk.Button(self.left_frame, text="撤销权限", command=self.revoke_executable).pack(pady=5)

        tk.Label(self.result_frame, text="操作结果").pack()
        self.result_text = scrolledtext.ScrolledText(self.result_frame, width=40, height=20)
        self.result_text.pack(fill="both", expand=True)

    def select_owner_path(self):
        path = filedialog.askdirectory()
        if path:
            self.owner_path_entry.delete(0, tk.END)
            self.owner_path_entry.insert(0, path)

    def select_owner_files(self):
        files = filedialog.askopenfilenames()
        if files:
            self.owner_path_entry.delete(0, tk.END)
            self.owner_path_entry.insert(0, ", ".join(files))

    def select_exec_file(self):
        file = filedialog.askopenfilename()
        if file:
            self.exec_path_entry.delete(0, tk.END)
            self.exec_path_entry.insert(0, file)

    def ask_password(self):
        if self.sudo_password is not None:
            return self.sudo_password
        password = simpledialog.askstring("需要权限", "请输入当前用户密码以使用 sudo:", show='*')
        return password

    def run_sudo_command(self, command, path, password):
        try:
            full_command = f"echo {quote(password)} | sudo -S {command} {quote(path)}"
            result = subprocess.run(full_command, shell=True, capture_output=True, text=True)
            if result.returncode == 0:
                # 如果密码正确且操作成功,缓存密码
                if self.sudo_password is None:
                    self.sudo_password = password
                return True, result.stdout
            else:
                # 如果密码错误,清空缓存并提示
                if self.sudo_password == password:
                    self.sudo_password = None
                return False, result.stderr
        except subprocess.SubprocessError as e:
            logging.error(f"sudo 命令执行失败: {str(e)}")
            return False, str(e)
        except Exception as e:
            logging.error(f"未知错误执行 sudo 命令: {str(e)}")
            return False, str(e)

    def change_owner(self, path_input, uid, target_user):
        if not path_input:
            messagebox.showerror("错误", "请指定路径或文件")
            return

        paths = [p.strip() for p in path_input.split(",")]
        invalid_paths = [p for p in paths if not os.path.exists(p)]
        if invalid_paths:
            messagebox.showerror("错误", f"以下路径不存在: {', '.join(invalid_paths)}")
            return

        try:
            for path in paths:
                if os.path.isdir(path):
                    for root_dir, dirs, files in os.walk(path):
                        os.chown(root_dir, uid, -1)
                        for file in files:
                            os.chown(os.path.join(root_dir, file), uid, -1)
                else:
                    os.chown(path, uid, -1)
            self.result_text.insert(tk.END, f"已将 {path_input} 及其子内容的所有者改为 {target_user}\n")
        except PermissionError:
            password = self.ask_password()
            if password:
                target_user_name = "root" if uid == 0 else self.current_user
                all_success = True
                for path in paths:
                    success, output = self.run_sudo_command(f"chown -R {target_user_name}", path, password)
                    if success:
                        self.result_text.insert(tk.END, f"使用 sudo 已将 {path} 及其子内容的所有者改为 {target_user}\n")
                    else:
                        all_success = False
                        messagebox.showerror("错误", f"sudo 操作失败: {output}")
                        self.result_text.insert(tk.END, f"修改 {path} 失败:{output}\n")
                if not all_success and self.sudo_password == password:
                    self.sudo_password = None  # 如果密码失效,清空缓存
            else:
                self.result_text.insert(tk.END, f"修改 {path_input} 失败:未提供密码\n")
        except OSError as e:
            messagebox.showerror("错误", f"系统错误: {str(e)}")
            self.result_text.insert(tk.END, f"修改 {path_input} 失败:{str(e)}\n")
            logging.error(f"OSError: {str(e)}")

    def change_owner_to_root(self):
        self.change_owner(self.owner_path_entry.get(), 0, "root")

    def change_owner_to_current(self):
        try:
            uid = os.getuid()
            self.change_owner(self.owner_path_entry.get(), uid, self.current_user)
        except OSError as e:
            messagebox.showerror("错误", f"无法获取当前用户 UID: {str(e)}")
            self.result_text.insert(tk.END, f"获取 UID 失败:{str(e)}\n")
            logging.error(f"获取 UID 失败: {str(e)}")

    def modify_executable(self, file, grant=True):
        if not file:
            messagebox.showerror("错误", "请指定文件")
            return

        if not os.path.exists(file):
            messagebox.showerror("错误", "文件不存在")
            return

        if not os.path.isfile(file):
            messagebox.showerror("错误", "请选择一个文件")
            return

        try:
            current_perms = os.stat(file).st_mode
            if grant:
                new_perms = current_perms | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
                action = "授予"
            else:
                new_perms = current_perms & ~(stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
                action = "撤销"
            os.chmod(file, new_perms)
            self.result_text.insert(tk.END, f"已{action} {file} 的可执行权限\n")
        except PermissionError:
            password = self.ask_password()
            if password:
                chmod_val = "+x" if grant else "-x"
                success, output = self.run_sudo_command(f"chmod {chmod_val}", file, password)
                if success:
                    self.result_text.insert(tk.END, f"使用 sudo 已{action} {file} 的可执行权限\n")
                else:
                    messagebox.showerror("错误", f"sudo 操作失败: {output}")
                    self.result_text.insert(tk.END, f"{action} {file} 失败:{output}\n")
                    if self.sudo_password == password:
                        self.sudo_password = None  # 如果密码失效,清空缓存
            else:
                self.result_text.insert(tk.END, f"{action} {file} 失败:未提供密码\n")
        except OSError as e:
            messagebox.showerror("错误", f"系统错误: {str(e)}")
            self.result_text.insert(tk.END, f"{action} {file} 失败:{str(e)}\n")
            logging.error(f"OSError: {str(e)}")

    def make_executable(self):
        self.modify_executable(self.exec_path_entry.get(), grant=True)

    def revoke_executable(self):
        self.modify_executable(self.exec_path_entry.get(), grant=False)


if __name__ == "__main__":
    try:
        root = tk.Tk()
        app = FilePermissionManager(root)
        root.mainloop()
    except Exception as e:
        logging.critical(f"程序启动失败: {str(e)}")
        messagebox.showerror("致命错误", f"程序启动失败: {str(e)}")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值