编注:本文记录了作者在没有过多终端脚本基础的情况下,通过「咨询」ChatGPT从无到有实现自动修复微信文件权限的过程。如果你对终端环境比较熟悉,文中提到的步骤和方法可能有些基础,解决方案也不一定是最优的。但我们认为这个探索过程是很有意义的,也体现了生成式AI与自动化结合的应用场景,值得推荐。
如果你需要本文方案的最简化、一次性实现,可以在终端运行:
find/"$HOME/Library/Containers/com.tencent.xinWeChat/Data/Library/ApplicationSupport/com.tencent.xinWeChat/"-typef-path/'*/*/Message/MessageTemp/*/File/*/'-execchmod644{};
▍引言
不知道从什么时候开始,在macOS上微信收到的文件都变成了只读,每次打开新文件,都需要另存一份。对于每天都需要用微信收发大量Word文档的我,这个改动非常折磨人。当然,最好的办法是不用微信,但这显然不是打工人可以决定的。
看到这行字就难受
好在,经过一些研究,我发现这个问题还是能够简单解决的,这里也将探索的过程分享给大家。需要说明的是,我不是相关方面的专业人士,本文所展示的几种方法未必是最合适的解决方案,特别是相关脚本是否存在风险还请自行判断。
▍一、自动操作
此前,我曾经在网上学过一个将Word文档保存为PDF文件的快速操作(QuickAction)指令,用途是批量将Word转换为PDF文档。因此,这次我首先也想到通过macOS系统里自带的自动操作(Automator)来实现这个目标。
修改Word文档等文件的权限,至少有三种方法。第一种是打开文档然后复制或另存文件;第二种是对文档右键选择「显示简介」,拉至下方将用户的权限修改为读和写(Read&Write)。
第三种方法看起来更像是适合批量操作的,用到的是chmod命令,具体而言,打开终端(Terminal.app),输入
chmod644/path/to/file
即可赋予用户读写的权限。
其中,644三个数字分别对应用户(所有者)、用户组和其他(所有人)的权限。4代表读的权限,2代表写的权限,1代表执行权限。用二进制写出来的话,就不难想象6(二进制110)可以表示读(4,二进制100)加上写(2,二进制010)的权限。至于文件路径,把需要的文件拖进终端就可以,注意chmod、644与文件路径之间均有空格。

图片来自网络
知道这个命令以后,我开始写快捷操作。一开始,我按照之前Word文档转PDF文件的经验使用了AppleScript,告诉(tell)终端(Terminal.app)去运行这行chmod命令。问题是,不仅运行时候会有个终端弹出,运行结束后终端也不会关闭,一直保留在dock栏上,即使按照网上的说法,使用exit命令加上修改profiles也不能完全解决。
奇怪于网络上为什么几乎没有人遇到相似问题,我才在检索中发现,根本没有必要使用AppleScript打开终端,在自动操作中运行一个Shell脚本就可以了。完整的操作过程如下:
•打开macOS自带的应用程序「自动操作(Automator)」,在弹出的新建窗口中双击选择「快速操作(QuickAction)」。
•在左侧的工具中找到,或者直接搜索「Shell」找到「运行Shell脚本(RunShellScript)」并双击或将其拖至右侧窗口。
•在右侧窗口设置为收到「文件或文件夹(filesorfolders)」,位于「访达(Finder.app)」,下方传递输入修改为「作为自变量(asarguments)」,然后在下方自动生成的模板中,将echo/"$f/"这一行替换为chmod644/"$f/"就可以了。整体如下图所示:

Shell中引用变量需要加$,就写下面那点东西的时间里我可能就忘了50次吧
•最后,保存并命名(比如:「修改权限」)。此外,也可以在上面的设置中修改图标和颜色。之后,在访达中,对任意文件右键选择「快速操作(QuickAction)」,点击刚才添加的「修改权限」操作,就能够立即将文件权限变更为读和写。
到这一步,问题得到了初步解决,在每次保存微信文件后,我只需要通过右键点击目标文件,再从快捷操作中选择上面创建的内容,就可以让随后打开的文档不再是「只读」。只不过,这样仍然有点麻烦,特别是忘记这一操作径直打开文档时,仍然有不通畅的感觉。
▍二、监控文件变动:认识fswatch工具
我的想法是,当我将微信中的文件保存到某个文件夹,如果这个文件夹里发生的变化能够被监测到,而发生变动后系统就自动运行一次上面的授权脚本,那么就不需要我手动点击快速操作按钮。
从这一步开始,我想到了ChatGPT。过去,我拿ChatGPT(GPT3.5版本)测试回答工作中遇到的法律问题,得到的结果并不令人满意。但考虑到ChatGPT在分析代码方面的能力,我非常期待它在帮助我这样外行人时的效果。结果是,ChatGPT的表现令我感到惊喜,在很多时候比搜索得到的结果更贴合我的问题,也更详细和耐心。
不过,在部分问题中,ChatGPT仍然会犯错,需要自行甄别或通过网络去检索更多和更新(尤其是在ChatGPT数据集截止日期以后)的解决方法。
(一)fswatch工具的安装
我询问ChatGPT的第一个问题是在macOS中是否有监控文件夹内文件发生变动就运行脚本的方法,ChatGPT告诉我fswatch工具可以实现这个目标。
ChatGPT告诉我fswatch需要通过Homebrew安装,fswatch的GitHub页面也给出了其他安装方法。在安装Homebrew后,在终端中输入brewinstallfswatch即可安装fswatch。
只是,在对话过程中,ChatGPT偶尔会忘记我在使用macOS这一前提,比如给我推荐inotifywait工具,在我尝试失败并检索后才发现,这是一个Linux上的命令。
欺骗了我的一些感情和一点时间
(二)选择被监控的文件范围
在脚本中,只需要输入fswatch文件路径就可以监控指定文件夹,同时,也可以添加一些更细化的参数以选择监控文件的范围。在这方面问题上,可能由于fswatch自身的版本更新,ChatGPT有时候能够迅速解决了我的问题,但有时候也会犯错导致我走弯路。
比如,我希望只在添加文件时触发事件,ChatGPT明确告诉我可以使用--eventCreate参数来实现。

但在我想要使用-i参数将添加的文件类型限制于.docx等文档时,ChatGPT就明显弄反了-i(include,包含)和-e(exclude,排除)两个参数。

这个回答有不止一处错误
考虑到授权陌生文件可能带来的风险,如何只监控特定文件恰恰是我比较关注的事项(当然,都监控然后加一个文件名判断也不是难事)。ChatGPT在这个问题上没有给我什么帮助。这里需要特别记录一下的是,fswatch命令中,只写-i并不意味着可以只监控符合规则的文件,必须首先写上-e并排除一切文件,再写一个-i包含需要的文件,才能够实现监控符合条件文件的目标。
上图的另一个错误在于,fswatch使用的匹配规则并非通配符,而是正则表达式(regex),当然这也可能是由于ChatGPT使用过时资料库导致的。在正则表达式中,匹配任意单字符的不是*而是.,任意数量字符则是.*。在学习和测试后,我将匹配部分写成如下形式:
#文件类型,可随意修改添加
types=(/"doc/"/"docx/"/"ppt/"/"pptx/"/"xls/"/"xlsx/")
#生成正则表达式
re=/"/"
foriin$;dore=/"$re|$i$/";done
re=$
#监控满足条件的文件变动
fswatch-e/".*/"-EIi$re--eventCreated$path
其中,re经过循环后生成的值为doc$|docx$|ppt$|pptx$|xls$|xlsx$,表示匹配以doc、docx等结尾的文件名。顺便一提,Shell在赋值的时候,=左右侧不能加空格,这写起来也太难受了。
fswatch的参数中,-e/".*/"表示排除所有(.*)文件。-EIi$re表示包含上述文件类型的文件,E(extended)和I(insensitive)的含义分别为使用扩展的正则表达式(否则无法使用或逻辑|),以及不区分大小写。$path则是目标文件夹,我事先定义了文件路径。
(三)对监控的文件做出修改
监控文件发生变化后,在如何修改变动文件权限的问题上,我一开始又使用了笨方法。我询问ChatGPT如何找到最后添加到文件,它在两次提问中分别给了我使用ls命令和find命令的方法,但我测试后发现这似乎找到的是最后修改文件,而非最后添加文件,这与我的需求不太符合。于是我使用了find$path-typef-perm444来查找整个文件夹内权限为「444」(只读)的文件并批量进行修改。
但当我返回查看ChatGPT最初给我的示例时,我意识到我可能把事情想复杂了。
这个例子帮了大忙
虽然暂时不知道|的具体作用,但上面这行示例代码的意思显然是,fswatch发现变动后,通过while循环和echo命令显示变动的文件,这看起来很符合我的要求。为此,我认真学习了管道|的用法……才怪咧,并没有那么多时间。显然,这里我只需要把echo$file修改为chmod644$file就可以了。
在readfile的过程中遇到了一个小问题,就是读取的文件名中如果有空格那么就会截断为两个变量。通过检索,将环境变量IFS修改为$/'n/'(换行)就能够让read变为逐行读取,解决这个问题。
整个脚本的代码展示如下:
#ChatGPT说,这是一个称为shebang的特殊注释,用于指定脚本解释器的路径
#如果该注释不存在或指定的路径不正确,则操作系统将尝试使用默认的解释器来执行脚本
#!/bin/bash
#自定义路径,这里以download文件夹为例
#实际上应该也可以直接修改为微信的缓存文件夹(可以通过右键点击微信内接收到的文件查看路径)
path=/"/Users/用户名/Downloads/"
#生成正则表达式,用于匹配文件
types=(/"doc/"/"docx/"/"ppt/"/"pptx/"/"xls/"/"xlsx/")
re=/"/"
foriin$;dore=/"$re|$i$/";done
re=$
#修改环境变量,让后面的read能够逐行读取
IFS=$/'n/'
#监控添加文件的事件,将变动文件传递至下面的chmod命令
fswatch-e/".*/"-EIi$re--eventCreated$path|
whilereadfile;do
#额外增加一个文件存在和不可写的判断,排除打开Word文档时产生的临时文件,避免报错
if[-f$file]&&![-w$file];then
chmod644$file
fi
done
最后,将文件保存为wxpermfix.sh(名称可以自己选择,保存路径按照惯例,可以放在自己主目录下的bin目录,即~/bin);并在终端里用chmod命令赋予其执行权限:chmod+x~/bin/wxpermfix.sh。
然后,就可以将它拖入终端中回车运行。
▍三、添加启动项文件:认识launchd
问题和麻烦从此刻开始不断涌现。
在写完以上脚本后,我打算让脚本自己跑起来,并在开机自动启动,ChatGPT推荐使用launchd工具。

注意修改Label和ProgramArguments下和包围的内容即可
可在我模仿上面的文件修改完毕(实际上只需要复制文件夹内随便一个其他文件就可以)后,出现了各种问题,包括但不限于:
•以为需要反复重启/登出用户来测试效果——实际上只需要launchctlunload卸载plist文件后launchctlload重新加载文件即可。
•加载时告诉我没有足够的权限——修改脚本和plist文件的权限,比较奇怪的是,似乎plist文件权限修改为744是不可以的,必须得644。
•放在什么位置——在ChatGPT提到的两个目录中,一开始我放在了/Library/LaunchDaemons,但那是系统级别的守护进程所在位置,放在那里会提示权限不足,实际上应该放在~/Library/LaunchAgent,以当前用户身份运行就行了。
•通过launchd启动不生效,但在终端中启动就可以——原因是launchd启动的进程的环境变量PATH与交互式终端下不同,无法找到fswatch,解决方式是找到fswatch命令的绝对路径,放在脚本里。

我早就把在脚本、plist文件中使用的目录都设置为绝对路径,所以一直没有理解ChatGPT发出的有关要使用绝对路径的提示,直到这里我才意识到是fswatch要使用绝对路径
•chmod报错权限不足——一开始我听信了ChatGPT的说法,以为需要在脚本中加上sudo,可那就意味着每次都需要输入密码,这显然是不符合我自动运行脚本需求的。

好在我最后在一个论坛里发现了解决方法,通过赋予bash完全磁盘访问权限(fulldiskaccess),可以让通过launchctl运行的脚本中的chmod命令有权限修改其他文件的权限。具体步骤还是可以问到:

至此,我终于有了一个可以自动启动的,不断监控目标文件夹的脚本。让我在微信自己解决这个问题以前,免受只读文件之苦。
如后文所述,因为不太想设置自动启动,我自己最后没有用这套方案。但如果有人想要用这套方案,请参考下列步骤,并请特别注意各处权限设置,否则会无法生效:
1.按照上面所示步骤赋予bash完全访问磁盘权限。
2.进入~/Library/LaunchAgents文件夹,创建一个内容如后附的wxpermfix.plist文件(除扩展名外名称可以自定)。打开后参照上面ChatGPT给出的示例,删去不需要的部分,修改Label和ProgramArguments字段中和包围的内容:前者就是一个单纯用于区分的名称(理论上可以随便填写,但惯例是采用反向DNS方式命名);后者则修改为上面wxpermfix.sh脚本的路径(注意把[USERNAME]部分换成自己的用户名)。
Label
com.example.wxpermfix
ProgramArguments
/Users/[USERNAME]/bin/wxpermfix.sh
RunAtLoad
3.打开终端(Terminal.app),输入launchctlload-w~/Library/LaunchAgents/wxpermfix.plist后回车,其中wxpermfix.plist的路径也可以不用手动输入,从Finder将其图标拖入终端窗口即可。
4.如果这么做没有生效,那么参照上面ChatGPT给出的方案,将wxpermfix.sh脚本中的fswatch,替换为运行whichfswatch命令找到的绝对路径,并重新加载一遍LaunchAgent:
launchctlunload~/Library/LaunchAgents/wxpermfix.plist
launchctlload~/Library/LaunchAgents/wxpermfix.plist
替代方案:不自动启动也不是不可以
在上面询问ChatGPT如何赋予bash完全磁盘访问权限时,ChatGPT提到了「存在一定的安全风险」。也许有的读者会介意这里的「安全风险」,因此我也就不推荐所有人采用上面的launchd方案。
我回想了一下平时的电脑使用习惯,我平时以待机为主,不经常关机,开机自动启动脚本也不是非要不可,只要启动后可以安静地自动运行就够了。所以,我又开始探索是否可以免去自动启动的要求。
在这里,我又走了一点弯路,我回到了自动操作(Automator),试图通过打包一个应用程序(Application)来实现目标,但运行时显示在上方状态栏的齿轮符号让我打消了这个念头。
于是,我问了ChatGPT最后一个问题,它的回答也一如既往的简洁和清楚。

当然,我自己是记不住nohup命令后面那几个参数的,所以我又写了一个新的.sh文件存放这条启动脚本的命令。等开机后,就将这个文件通过终端运行一次,然后就可以退出终端,让修改权限脚本保持运行。与之对应的是,我也写了一条关掉脚本的指令备用,存在同一个文件夹的另一个.sh脚本中。
这两个文件分别为,启动:
#!/bin/bash
#启动xxx.sh,替换为正确路径即可
nohupxxx.sh>/dev/null2>&1&
关闭:
#!/bin/bash
#关闭xxx.sh,替换为正确文件名即可
pkill-fxxx.sh
▍题外话
在此之前,我从来没有写过Shell脚本,否则也不会在一开始干出在自动操作中tell/"Terminal.app/"的事情。虽然学习过程中也遇到了不少问题,但整体上还是比较愉悦和流畅的。一个原因可能在于,对于从零开始的学习者而言,ChatGPT在每个问题上都提供了详尽有用的解释和非常具体的示例,非常直观和有效。
当然,ChatGPT好用也不意味着可以对其无条件信任,在解决问题时,查看文档和搜索引擎仍然是有必要的。并且,比起高度抽象地描述问题让它给出完整方案,一步步提问可能对学习和检验都更有帮助。
一点额外的感想是,就像我在ChatGPT中提问自身专业知识时,很容易看出它从什么时候开始胡编乱造,相信计算机专业人士在使用ChatGPT中也能更高效地甄别信息的真伪,更直接地去利用那些更有价值的东西,扬弃错误和冗余的部分。我想,这某种程度上或许也说明了专业人士并不那么容易因AI发展而被替代,反而是比起一般人在利用AI解决相关问题时更有优势吧。
https://sspai.com/post/79351?utm_source=wechat&utm_medium=social
作者:GoodTheme
责编:PlatyHsu
题图来自Unsplash:@imkirk
未经允许不得转载:头条资讯网_今日热点_娱乐才是你关心的时事新闻 » 微信文件变成“只读”?我用 ChatGPT 找到了解决方法
头条资讯网_今日热点_娱乐才是你关心的时事新闻








