在 Mac 上将当天的日历事项导出为 TXT 文件

我经常使用Mac上的日历应用,公司每天也要写日报,于是将日历中当天的事项导出为TXT文件,可以省下很多心力做其他事情。我尝试了将近一个月,感觉不错。

本文将详细介绍如何使用 AppleScript 实现这一目标。通过简单的脚本,可以获取当天所有的日历事件,将它们导出到一个带有当前日期的TXT文件中,显示导出的记录数量。如果结合 crontab 还能完成定时自动导出的工作,甚至,结合selenium,还可以自动化填写日报。

前提条件

在开始之前,请确保你已经授予 AppleScript 访问日历的权限。如果这是你第一次运行此脚本,系统可能会提示你授权访问。

脚本说明

以下是完整的 AppleScript 脚本,确保从当天凌晨0点到当天晚上12点之间的“日常”下的所有日历事件,并将它们导出到桌面的TXT文件中。文件名将包含当前日期,并在完成导出后显示一个弹窗,告知导出的记录数量。

tell application "Calendar"
    -- 获取当前日期
    set currentDate to current date
    
    -- 设置今天的开始时间为凌晨0点
    set startOfDay to currentDate
    set time of startOfDay to 0
    
    -- 设置今天的结束时间为晚上12点
    set endOfDay to startOfDay + 1 * days

    -- 获取"日常"日历中的今天的事件
    set theEvents to (get events of calendar "日常" whose start date ≥ startOfDay and start date < endOfDay)
    
    set eventDetails to ""
    repeat with theEvent in theEvents
        set eventDetails to eventDetails & (summary of theEvent) & " - " & (start date of theEvent) & return
    end repeat
    
    -- 获取当前日期的年月日
    set {year:y, month:m, day:d} to (current date)
    set monthText to text -2 thru -1 of ("0" & (m as integer) as string)
    set dayText to text -2 thru -1 of ("0" & (d as integer) as string)
    set dateText to (y as string) & "-" & monthText & "-" & dayText
    
    -- 设置文件名
    set fileName to "daily-" & dateText & ".txt"
    
    -- 导出事件到文件
    do shell script "echo " & quoted form of eventDetails & " > ~/Desktop/" & fileName
    
    -- 显示导出记录数量的弹窗
    display dialog "导出了 " & (count of theEvents) & " 条记录。" with title "导出完成"
end tell

使用步骤

  1. 打开“脚本编辑器”: 在你的Mac上,打开“脚本编辑器”应用程序。这是macOS自带的一个应用,可以用来编写和运行AppleScript脚本。
  2. 粘贴脚本: 将上述脚本复制并粘贴到“脚本编辑器”中。
  3. 修改日历名称: 如果你使用的日历名称不是“日常”,请修改脚本中 set theEvents to (get events of calendar "日常" whose start date ≥ startOfDay and start date < endOfDay) 中的 "日常" 为你具体的日历名称。
  4. 运行脚本: 点击“运行”按钮,脚本将开始执行。

image-20240719上午90423490

修改

我做了一些细微调整:

tell application "Calendar"
	-- 获取当前日期
	set currentDate to current date
	-- 设置某个日期
	-- set currentDate to date "2024年7月23日 上午12:00:00"
	
	-- 设置今天的开始时间为凌晨0点
	set startOfDay to currentDate
	set time of startOfDay to 0
	
	-- 设置今天的结束时间为晚上12点
	set endOfDay to startOfDay + (1 * days)
	
	-- 获取"日常"日历中的今天的事件
	set theEvents to (get events of calendar "日常" whose start date ≥ startOfDay and start date < endOfDay)
	
	set eventDetails to ""
	set eventCount to count of theEvents
	set eventNumber to 1
	
	-- 构建总结性内容
	-- set summaryContent to "当前日期: " & (startOfDay as string) & " - 总共: " & eventCount & " 个日历事项" & return & return
	set summaryContent to "共" & eventCount & "个事项:" & return
	
	repeat with theEvent in theEvents
		-- 获取事件的开始时间
		set eventStartDate to start date of theEvent
		
		-- 提取时间部分并格式化
		set eventTime to time of eventStartDate
		
		-- 减去8小时调整时间,有时候有偏移,就手动改一下,没有就-0
		set adjustedTime to eventStartDate - (0 * hours)
		
		-- 格式化调整后的时间为字符串
		set timeString to (time string of adjustedTime)
		
		-- 格式化事件编号
		if eventNumber < 10 then
			set formattedNumber to "0" & eventNumber
		else
			set formattedNumber to eventNumber as string
		end if
		
		-- 构建事件详情字符串(仅内容)
		set eventDetails to eventDetails & formattedNumber & ". " & (summary of theEvent) & return
		
		-- 构建事件详情字符串(包含时间)
		-- set eventDetails to eventDetails & formattedNumber & ". " & (summary of theEvent) & " - " & timeString & return
		set eventNumber to eventNumber + 1
	end repeat
	
	-- 获取当前日期的年月日
	-- set {year:y, month:m, day:d} to (current date)
	-- 获取 startOfDay 的年月日
	set {year:y, month:m, day:d} to startOfDay
	set monthText to text -2 thru -1 of ("0" & (m as integer) as string)
	set dayText to text -2 thru -1 of ("0" & (d as integer) as string)
	set dateText to (y as string) & "-" & monthText & "-" & dayText
	
	-- 设置文件名
	set fileName to "daily-" & dateText & ".txt"
	
	-- 导出事件到文件
	-- do shell script "echo " & quoted form of (summaryContent & eventDetails) & " > ~/Desktop/" & fileName
	do shell script "echo " & quoted form of (summaryContent & eventDetails) & " > ~/Desktop/" & fileName
	
	-- 显示导出记录数量的弹窗
	-- display dialog "导出了 " & (count of theEvents) & " 条记录。" with title "导出完成"
end tell

因为平时更习惯用shell,所以我还配合写了一个shell脚本,方便 crontab 调用:

#!/bin/bash

# 获取当前年份和周数
YEAR=$(date +%y)   # 获取当前年份的最后两位,例如 24
WEEK=$(date +%V)   # 获取当前周数,例如 16

# 获取当前日期的文件名
TODAY=$(date +%Y-%m-%d)  # 格式为 YYYY-MM-DD
FILENAME="daily-${TODAY}.txt"

# 组合目录名
DIRECTORY_NAME="${YEAR}${WEEK}"

# 目标路径
TARGET_PATH="/Users/kelu/Library/Mobile Documents/com~apple~CloudDocs/${DIRECTORY_NAME}"

# 创建目录
mkdir -p "${TARGET_PATH}"

osascript "/Users/kelu/Library/Mobile Documents/com~apple~ScriptEditor2/Documents/导出今天日历.scpt"

# 源文件路径
SOURCE_FILE="/Users/kelu/Desktop/${FILENAME}"

# 移动文件
if [ -f "${SOURCE_FILE}" ]; then
    mv "${SOURCE_FILE}" "${TARGET_PATH}/"
    echo "文件已移动: ${SOURCE_FILE} -> ${TARGET_PATH}/"
else
    echo "文件未找到: ${SOURCE_FILE}"
fi

在 macOS 一次性关闭所有 chrome 实例 和 Finder 窗口

关闭 Chrome 实例

有时候自动化程序会打开很多个chrome实例,可以这样批量关闭。

  1. 打开终端。

  2. 在终端中输入以下命令并按下回车键:

    killall -9 "Google Chrome"
    

解释

  • killall 是一个用来终止所有给定进程名称的工具。
  • -9 选项表示发送SIGKILL信号,这是一个强制终止信号,告诉操作系统立即终止进程,而不进行正常的清理操作。
  • "Google Chrome" 是你要终止的应用程序的名称,记得使用双引号括起来,因为名称中有空格。

关闭所有 Finder窗口

关于 osascript 的更多内容参考我这篇文章 《使用 osascript 命令将 Mac 应用切换到前台》

osascript -e 'tell application "Finder" to close every window'

在 macOS 上为顶级域名设置特定的 DNS 服务器

有好些方式,例如自建dns,就是最灵活的解决方案。如果不需要那么多的特性,可以通过配置 resolver 文件,可以为特定的域名甚至顶级域名设置特定的 DNS 服务器。本文将介绍如何为顶级域名 .abc 设置使用 DNS 服务器 1.2.3.4

步骤 1:创建 resolver 文件夹

首先,需要确保 /etc/resolver 文件夹存在。这个文件夹将存放特定域名的 DNS 配置文件。

打开终端并运行以下命令:

sudo mkdir -p /etc/resolver

步骤 2:为顶级域名 .abc 创建配置文件

接下来,我们需要为顶级域名 .abc 创建一个配置文件。在终端中运行以下命令创建并编辑配置文件:

sudo vim /etc/resolver/abc

在文件中添加以下内容:

nameserver 1.2.3.4

步骤 3:测试配置

配置完成后,可以通过以下命令测试 DNS 配置是否生效:

nslookup example.abc

结果应该显示 DNS 查询是通过 1.2.3.4 进行的:

Server:         1.2.3.4
Address:        1.2.3.4#53

Non-authoritative answer:
Name:   example.abc
Address: <IP_ADDRESS>

防止AirPods 自动连接至 Mac/iPhone/iPad

在Mac上:

  1. 打开“系统设置”(macOS Ventura 及以上版本)或“系统偏好设置”(macOS Monterey 及以下版本)。

  2. 选择“AirPods”

    image-20240617上午82139846

  3. 在“连接到此Mac”选项下,不选择自动,选择“上次连接到此Mac时。

  4. 选择后,如果断开AirPods,就找不到这个侧边栏选项了。

  5. iPhone iPad也是类似。

    IMG_8078


Anki 简单实用的记忆神器

最近接触的Anki。稍微记录一些它的情况。Anki 是一款备受欢迎的记忆软件,帮助用户有效地记忆各种信息。官方网站 AnkiWeb

Anki 的基本功能

  1. 间隔重复:Anki 的核心功能是基于艾宾浩斯遗忘曲线理论,通过在适当的时间间隔内重复呈现卡片,帮助用户将信息从短期记忆转化为长期记忆。这种方法被证明可以显著提高记忆效果,减少遗忘。

  2. 卡片库:Anki 提供了一个庞大的卡片库,用户可以根据自己的需求下载现成的卡片库,也可以自行创建卡片。AnkiWeb 上有丰富的共享卡片库,涵盖了从语言学习到医学考试的各个领域。下面这两个卡片库是我目前暂时使用的:
  3. 多平台支持:Anki 支持多种平台,包括 Windows、Mac、Linux、iOS 和 Android,这意味着你可以在任何设备上进行学习,并且数据可以通过 AnkiWeb 实现同步。
  4. 高度自定义:用户可以根据个人需求自定义卡片格式,添加图片、音频、视频等多种媒体,使学习过程更加生动有趣。你还可以使用 Anki 的插件系统来扩展其功能,根据自己的需求调整软件的表现。d

使用 Anki 的实用技巧

  1. 每日坚持:记忆的关键在于每天坚持使用 Anki 进行复习,即使每次只有几分钟,也能带来显著的效果。

  2. 分散学习:将学习任务分散到一天中的不同时间段,而不是一次性完成大量的学习,这样可以提高记忆效果。

  3. 创建高质量卡片:高质的卡片应该简洁明了,每张卡片只包含一个信息点,避免信息过载。

  4. 利用共享卡片库:对于一些通用知识点,如语言学习和考试准备,可以充分利用 AnkiWeb 上的共享卡片库,这样可以节省时间并获得高质量的学习资源。


解决 Homebrew 更新时的 "No remote 'origin'" 警告问题

今天在某台Mac在使用 Homebrew 更新包管理器时,我遇到这样一个警告:

brew update
==> Updating Homebrew...
Warning: No remote 'origin' in /opt/homebrew/Library/Taps/homebrew/homebrew-services, skipping update!

image-20240531上午103103101

这条警告信息是说,Homebrew 的 homebrew-services tap 没有设置远程 origin,这会阻止它的更新。这通常是由于 tap 添加不正确或其远程 URL 被移除导致的。

解决方法

1. 取消有问题的 tap

brew untap homebrew/services

2. 重新添加 tap

brew tap homebrew/services

3. 更新 Homebrew

brew update

这个命令会更新 Homebrew 及其所有的 taps,包括重新添加的 homebrew/services

image-20240531上午104610171

Happy brewing! 🍻


如何检查 iOS ipa 文件的签名信息

方法一:使用 codesign 工具

codesign 是 macOS 自带的工具,可以用来检查应用的签名信息。以下是具体步骤:

  1. 解压 IPA 文件: IPA 文件其实是一个 ZIP 压缩包,先将其解压缩。

    unzip MyApp.ipa
    
  2. 找到应用包: 解压后,你会得到一个 Payload 文件夹,里面有一个 .app 文件夹。

  3. 使用 codesign 检查签名

    codesign -dvvv Payload/MyApp.app
    

    这条命令会显示详细的签名信息。

方法二:使用 codesign 结合 ldid 工具

ldid 工具可以更详细地查看签名信息,尤其是在查看 entitlements(权限)方面。

  1. 安装 ldid: 首先需要安装 ldid,可以使用 Homebrew 安装:

    brew install ldid
    
  2. 使用 ldid 检查签名

    ldid -e Payload/MyApp.app/MyApp
    

    这条命令会显示应用的 entitlements 信息。

方法三:使用第三方工具

  • iOS App Signer
  • iFunbox