这是现在基本上所有电脑都能实现的功能了,无非就是后台自动搜索设备,然后自动挂载。可能这个场景在没有GUI版的Linux用处不大,导致每次插入U盘都得手动挂载一遍,于是决定写个脚本实现自动挂载。
我们要实现的效果就是,插入U盘,系统自动把U盘挂载在/path-to-mount/label路径下,label是U盘的名称(注意不要插入两张Label名字相同的SD卡)。
自动挂载
-
查看SD卡在miniPC的挂载路径
lsblk可以得到
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS sda 8:0 0 476.9G 0 disk ├─sda1 8:1 0 512M 0 part /boot/efi ├─sda2 8:2 0 475.5G 0 part / └─sda3 8:3 0 976M 0 part [SWAP] sdb 8:16 1 58.9G 0 disk └─sdb1 8:17 1 58.9G 0 part sdc 8:32 1 0B 0 disk可以看到
sdb1就是我的SD卡,但是目前还没有挂载 -
sdb1为一个文件,他的位置在/dev/sdb1,我们找到这个SD卡的UUIDsudo blkid /dev/sdb1 /dev/sdb1: LABEL="Nikon-1" UUID="4A21-0000" BLOCK_SIZE="512" TYPE="exfat" PTTYPE="dos"其中
LABEL就是你给U盘的命名,插入U盘后电脑显示的U盘的名字。 -
创建脚本
/usr/local/bin/auto-mount-usb.sh#!/usr/bin/env bash logfile="/var/log/udev-usb-label.log" mount_base="/base-path-to-mount" exec >> "$logfile" 2>&1 logger "Auto-mount script triggered: $@" LABEL="$1" [[ -z "$LABEL" ]] && { logger "No LABEL provided" exit 1 } DEVICE=$(readlink -f "/dev/disk/by-label/$LABEL") if [[ ! -b "$DEVICE" ]]; then logger "Device for label $LABEL not found" exit 1 fi MOUNTPOINT="$mount_base/$LABEL" mkdir -p "$MOUNTPOINT" logger "Mounting $DEVICE to $MOUNTPOINT" if /usr/bin/mount -t auto -o uid=1000,gid=1000,umask=0022,iocharset=utf8 "$DEVICE" "$MOUNTPOINT"; then logger "Mounted $LABEL to $MOUNTPOINT successfully" else logger "Failed to mount $LABEL" exit 1 fi- Log files放在了
/tmp,重启后会自动清理 - 需要修改一下挂载点
mount_base="/base-path-to-mount",假设我都放在/home/username/,每插入U盘,就会在这个文件夹下以U盘的Label为名字创建新的文件夹,注意不要插入两张Label相同的SD卡
- Log files放在了
-
刷新脚本权限
sudo chmod +x ./auto-mount-usb.sh -
创建systemd服务
/etc/systemd/system/[email protected][Unit] Description=Auto Mount USB LABEL=%i After=local-fs.target [Service] Type=oneshot ExecStart=/usr/local/bin/auto-mount-usb.sh %i -
新建规则文件
/etc/udev/rules.d/99-auto-usb-mount.rulesACTION=="add", SUBSYSTEM=="block", ENV{ID_FS_LABEL}!="", ENV{SYSTEMD_WANTS}+="auto-mount-usb@%E{ID_FS_LABEL}.service" -
重新加载
sudo udevadm control --reload-rules sudo udevadm trigger sudo systemctl daemon-reload
这样当你在Linux中新插入U盘后,就会在特定的位置新创建一个文件夹,然后访问你U盘的文件了
卸载U盘
当希望拔出U盘时,一定要先卸载U盘,否则有可能造成文件损坏,我们这里还是先使用手动的卸载方法,输入命令
sudo umount /path_to_disk
如果什么也不返回,就可以安全地插拔U盘了,如果挂载点被占用,可以查看被谁占用(注意如果终端在U盘路径内也会卸载不成功):
sudo lsof +D /path_to_disk
卸载之后在本地的文件夹不会删除,变成了普通的文件夹,如果需要可以手动删除。
Raw文件
挂载U盘 / SD卡很大原因是为了配合File Browser自建文件浏览器,方便传送文件给朋友,比如我把相机插到miniPC上,朋友就可以访问和下载相机SD卡的照片。我的相机是Nikon Zfc,它可以配置拍一次照片导出一张RAW文件(.NEF)用于精修,一张.jpg用于预览。但是File Browser是无法在线预览RAW文件的。所以我们可以在/usr/local/bin/auto-mount-usb.sh脚本里添加一步,比如插入名为nikon-x的SD卡后自动把RAW文件挪到一个新建的子文件夹中,然后在File Browser里就可以分类显示.jpg和.NEF了。
# ---------------- Nikon 文件分类逻辑 ----------------
if [[ "$LABEL" == nikon-* ]]; then
logger "Detected Nikon device. Scanning for image files..."
TARGET_DIR="$MOUNTPOINT/DCIM/102NZ_FC"
RAW_DIR="$TARGET_DIR/RAW"
JPG_DIR="$TARGET_DIR/JPG"
if [[ -d "$TARGET_DIR" ]]; then
mkdir -p "$RAW_DIR" "$JPG_DIR"
# 移动 RAW 文件 (.NEF)
find "$TARGET_DIR" -maxdepth 1 -type f -iname "*.nef" -exec mv {} "$RAW_DIR" \;
# 移动 JPG 文件
find "$TARGET_DIR" -maxdepth 1 -type f -iname "*.jpg" -exec mv {} "$JPG_DIR" \;
logger "Finished organizing files into RAW and JPG folders"
else
logger "Target directory $TARGET_DIR not found. Skipping file classification."
fi
fi
LRF文件
同样大疆在拍摄视频之后会出现一个LRF文件和一个MP4文件,我们可以加入这条命令让其自动区分
# ---------------- DJI 文件分类逻辑 ----------------
if [[ "$LABEL" =~ ^dji-[0-9]+$ ]]; then
logger "Detected DJI device. Scanning for video and LRF files..."
TARGET_DIR="$MOUNTPOINT/DCIM/DJI_001"
LRF_DIR="$TARGET_DIR/LRF"
MP4_DIR="$TARGET_DIR/MP4"
if [[ -d "$TARGET_DIR" ]]; then
mkdir -p "$LRF_DIR" "$MP4_DIR"
# 移动 .LRF 文件
find "$TARGET_DIR" -maxdepth 1 -type f -iname "*.lrf" -exec mv {} "$LRF_DIR" \;
# 移动 .MP4 文件
find "$TARGET_DIR" -maxdepth 1 -type f -iname "*.mp4" -exec mv {} "$MP4_DIR" \;
logger "Finished organizing DJI files into LRF and MP4 folders"
else
logger "Target directory $TARGET_DIR not found. Skipping file classification."
fi
fi
注意事项
- 配合File Browser的Docker容器使用时,需要先挂载USB,然后再运行Docker容器,否则会找不到文件,如果容器已经运行,可以down再up重启一遍
- 这样脚本在插入USB后就会马上对文件进行分类,建议先做备份,然后再插入miniPC,以免造成文件丢失
- 假设有一部分未分类,有一部分已分类,程序会只把未分类的归类,反复插拔U盘不会造成影响
- 如果有相同名称的有可能会造成文件丢失,但是Nikon会按照快门数给照片分配ID,因此问题不大
udevil
相比于自己写脚本,也可以使用udevil
-
安装
sudo apt update sudo apt install udevil -
修改配置文件
/etc/udevil/udevil.confallowed_media_dirs = /media/$USER, /run/media/$USER可以把默认路径写在这里,越往前优先级越高,放在第一位就是默认路径
-
创建服务文件
sudo nano /etc/systemd/system/devmon.service[Unit] Description=Devmon Auto-mount Service After=network.target [Service] Type=simple User=<your_username> Group=<your_username> ExecStart=/usr/bin/devmon Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target -
重新加载配置
sudo systemctl daemon-reload sudo systemctl restart devmon