是的,在 macOS 上默认是没有 smbclient
的(它是 Samba 套件的一部分,Linux 常见)。不过你仍然可以用系统自带的命令或者方式来访问 SMB 共享:
可替代方法
1. mount_smbfs
macOS 自带的挂载命令:
示例:
注意:如果密码里有特殊符号,需要 URL 编码(比如 @
→ %40
)。
卸载:
2. open
(调用 Finder)
直接通过命令行调起 Finder 连接 SMB:
这会在 Finder 里挂载共享盘。
3. osascript
(AppleScript)
如果你想脚本化,可以用 AppleScript:
4. 如果真的需要 smbclient
可以通过 Homebrew 安装 Samba:
然后你就能用熟悉的 smbclient
命令了。
👉 总结:
如果只是想访问/挂载共享,推荐用 mount_smbfs
或 open smb://
。
如果需要像 Linux smbclient
那样交互式操作(比如 ls
, get
, put
),就要装 samba
提供的 smbclient
。
要不要我帮你写一个 基于 mount_smbfs
的脚本,模拟 smbclient ls/get/put
的功能?
macos 用 mount_smbfs 命令 来代替的 smbclient 的功能
👌 好的,那我们把 smbclient
逻辑改成 mount_smbfs
。
原理
示例脚本
脚本说明
mount_smbfs "//$SMBUSER:$SMBPASS@$REMOTE_HOST/$REMOTE_SHARE" "$MOUNT_POINT"
→ 把远程 SMB 共享挂载到 /Volumes/KKKKK_Audit
mkdir "$MOUNT_POINT/$TARGET_DIR"
→ 在远程共享里新建目标目录
cp -n
→ 复制文件,如果目标已存在则不覆盖(防止重复)
⚠️ 注意:
mount_smbfs
需要 目标目录为空 或者是个挂载点。
用户密码写在脚本里不太安全,可以考虑放进 Keychain 或者用 ~/.nsmbrc
保存认证信息。
挂载完成后,你也可以手动进入 /Volumes/KKKKK_Audit/11111111
查看文件。
要不要我帮你写一个 自动卸载(umount)共享盘 的版本,这样脚本跑完后不会一直挂着远程共享?
要
好的 ✅ 我给你加上 自动卸载远程 SMB 共享盘 的逻辑:
改进后的完整脚本
逻辑改进点
变量 MOUNTED_BY_SCRIPT
如果是脚本挂载的 → 结束时卸载
如果脚本执行前就已挂载 → 不卸载,避免影响别人
umount "$MOUNT_POINT"
复制文件时 cp -n
要不要我再帮你加一个 日志功能(比如把每次复制的文件路径和时间写到一个 log 文件里 /var/tmp/copy_to_smb.log
),方便后面排查?
# 搜索并复制文件 mdfind '((kMDItemFSName == "*BBBB*"cd) || (kMDItemFSName == "*AAAA*"cd) || (kMDItemFSName == "*CCCC*"cd) || (kMDItemFSName == "*DDDD*"cd) || (kMDItemFSName == "*EEEE*"cd)) && ((kMDItemFSName == "*.pdf"cd) || (kMDItemFSName == "*.ppt"cd) || (kMDItemFSName == "*.pptx"cd) || (kMDItemFSName == "*.key"cd) || (kMDItemFSName == "*.png"cd) || (kMDItemFSName == "*.jpg"cd) || (kMDItemFSName == "*.jpeg"cd))' -0 | \ while IFS= read -r -d '' file; do if [[ "$file" != /Library/* && "$file" != /System/Library/* ]]; then echo "正在复制: $file" cp -n "$file" "$MOUNT_POINT/$TARGET_DIR/" fi done 我要判断 当搜索到文件时 才挂载
我想挂载的时候,让用户看不到挂载的盘
明白 ✅。在 macOS 里,mount_smbfs
默认会把 SMB 共享挂载到 /Volumes/共享名
,然后用户在 Finder 里会看到一个「磁盘」。如果你想做到「用户看不到挂载的盘」,有几种办法:
方案 1:挂载到隐藏目录
你完全可以把挂载点放在一个以 .
开头的目录里(Finder 默认隐藏),比如:
然后:
这样就挂载到 /tmp/.smb_mount
,Finder 默认不会显示 /tmp
里的挂载。
方案 2:挂载到 /Volumes
下的隐藏目录
如果你还是想挂载到 /Volumes
,也可以取个隐藏目录:
挂载后 Finder 不会显示这个卷。
方案 3:挂载后设置「不显示」属性
即使挂载在 /Volumes/KKKKK_Audit
,你也可以给挂载点设置 hidden
属性:
这样 Finder 里就不会显示这个挂载点,但程序依然能访问。
推荐做法
最简单、安全的是 方案 1:直接挂载到 /tmp/.smb_mount
(或者 /var/tmp/.smb_mount
),这样不会出现在 Finder,也不用改系统属性。
要不要我帮你改一下之前的完整脚本,把挂载点改成「隐藏目录挂载」版本,并自动清理掉挂载点目录?
#!/bin/zsh #
REMOTE_HOST="192.168.77.220"
REMOTE_SHARE="KKKKK_Audit$"
MOUNT_POINT="/tmp/.smb_mount"
SMBUSER="myusername"
SMBPASS="mypassword》}"
ComputerName=$(scutil --get ComputerName)
Serial=$(system_profiler SPHardwareDataType | grep "Serial Number" | awk '{print $4}')
Version="$(sw_vers -productName) $(sw_vers -productVersion)" #IP=$(ifconfig | grep "inet " | grep -v 127.0.0.1 | head -n 1 | awk '{print $2}')
wired_mac=$(networksetup -listallhardwareports | awk '/Hardware Port: Ethernet/{getline; getline; print $3}'| head -n 1 ) wireless_mac=$(networksetup -listallhardwareports | awk '/Hardware Port: Wi-Fi/{getline; getline; print $3}'| head -n 1 ) curr_user=$(id -un)
TARGET_DIR="${curr_user}"
# 先把搜索结果存到数组里
files=() while IFS= read -r -d '' file;
do
if [[ "$file" != /Library/* && "$file" != /System/Library/* ]]; then files+=("$file") fi done < <(mdfind '((kMDItemFSName == "*BBBB*"cd) || (kMDItemFSName == "*AAAA*"cd) || (kMDItemFSName == "*CCCC*"cd) || (kMDItemFSName == "*DDDD*"cd) || (kMDItemFSName == "*EEEE*"cd)) && ((kMDItemFSName == "*.pdf"cd) || (kMDItemFSName == "*.ppt"cd) || (kMDItemFSName == "*.pptx"cd) || (kMDItemFSName == "*.key"cd) || (kMDItemFSName == "*.png"cd) || (kMDItemFSName == "*.jpg"cd) || (kMDItemFSName == "*.jpeg"cd))' -0) if [[ ${#files[@]} -eq 0 ]];then (/usr/bin/osascript -e "display dialog \"没有关键字文件\" buttons {\"OK\"} default button \"OK\" with title \"敏感文件\" ")
exit 0
fi
# 确保挂载点目录存在
if [[ ! -d "$MOUNT_POINT" ]]; then sudo mkdir -p "$MOUNT_POINT" fi # 如果没挂载,挂载共享 if ! mount | grep -q "$MOUNT_POINT"; then mount_smbfs "//$SMBUSER:$SMBPASS@$REMOTE_HOST/$REMOTE_SHARE" "$MOUNT_POINT" fi
# 判断远程目录是否存在,不存在就创建
if [[ ! -d "$MOUNT_POINT/$TARGET_DIR" ]]; then
mkdir "$MOUNT_POINT/$TARGET_DIR"
fi
# 复制文件
for file in "${files[@]}"; do
echo "正在复制: $file" \cp -f "$file" "$MOUNT_POINT/$TARGET_DIR/"
done
#卸载
umount "$MOUNT_POINT"
exit 0
mount_smbfs: URL parsing failed, please correct the URL and try again: Invalid argument mkdir: /tmp/.smb_mount/mmmmm: Permission denied 正在复制: /Users/mmmmm/CCCC.pdf cp: directory /tmp/.smb_mount/mmmmm does not exist 正在复制: /Users/mmmmm/AAAA.pptx cp: directory /tmp/.smb_mount/mmmmm does not exist 正在复制: /Users/mmmmm/AAAA.ppt cp: directory /tmp/.smb_mount/mmmmm does not exist umount: /tmp/.smb_mount: not currently mounted
你这个脚本报错主要有两个点:
1. mount_smbfs: URL parsing failed
报错说明 SMB 路径写得不对。
在 macOS 里,mount_smbfs
的 URL 必须符合下面格式:
你的写法:
问题出在 REMOTE_SHARE="KKKKK_Audit$"
—— $
在 zsh 里会被当成变量展开。
所以实际上传给 mount_smbfs
的路径不正确。
✅ 解决办法 → 对共享名里的 $
进行转义:
2. mkdir: /tmp/.smb_mount/mmmmm: Permission denied
说明 SMB 挂载没有成功,所以 /tmp/.smb_mount
还是本地目录,不是远程目录。
因此你在上面 mkdir "$MOUNT_POINT/$TARGET_DIR"
的时候,其实是在本地 /tmp/.smb_mount
下建目录(而且你用了 sudo mkdir -p "$MOUNT_POINT"
创建,root 拥有它 → 普通用户就没权限写入)。
✅ 解决办法 →
修正后的脚本关键部分
3. 建议加的健壮性
挂载后再检查是否真的成功:
这样能避免后续 mkdir
、cp
报一堆错。
要不要我帮你把整个脚本整理一下,改成 自动判断挂载是否成功 → 再复制文件 → 最后卸载 的稳定版?
# mount_smbfs "//myusername:mypassword}>@$192.168.77.220/KKKKK_Audit\$" "/tmp/.smb_mount"
mount_smbfs: URL parsing failed, please correct the URL and try again: Invalid argument
嗯,这个报错是因为 密码里有特殊字符(>
、}
、$
等)和 共享名里的 $
,在 mount_smbfs
的 URL 里没被正确转义。
macOS 的 mount_smbfs
是非常挑剔的,它要求 URL 必须符合:
解决办法有三种:
✅ 方法 1:用引号和百分号转义特殊字符
mount_smbfs
遵循 URL 编码规则,例如:
>
→ %3E
}
→ %7D
$
→ %24
{
→ %7B
所以你的命令应该改成:
✅ 方法 2:避免在命令里写密码
推荐使用 凭证文件 或 ~/.nsmbrc
(安全很多):
编辑 ~/.nsmbrc
权限保护
挂载时就不用写密码了:
✅ 方法 3:让脚本运行时交互输入密码
建议
如果是长期要用的自动化脚本 → 用 方法 2 (~/.nsmbrc
) 最稳妥;
如果只是测试 → 用 方法 1 URL 编码 就能解决你现在的报错。
要不要我帮你把你的整个脚本改成 方法 2(用 ~/.nsmbrc
免密码) 的安全版本?