褪尘矗心

Bash 脚本删除 Mac 生成隐藏文件

从 Mac 转至 Ubuntu20.04,文件夹都带着 Mac 尊贵的烙印,即 .DS_Store 文件,GUI + 鼠标点击(+ 键盘敲击)显然是不适合 Linux 使用者的,Bash 作为优秀的脚本语言,确实应该用它来做重复劳动力的事。(其实实现这个功能,只需要 find + rm 命令即可实现,所以我能找到的此删除脚本的唯一特点是利用 GUI,直接将需处理目录拖至 Terminal,可能比直接敲 tab 快???一个只会基本操作的 Linux 用户,还是“可能”吧。)


WBS

Thumbs.db 是一个“缩略图数据库”,并不是 macos 独有的,但是迁移加“洁癖”,我只希望留下真正需要的东西,如果不想删除,可以在判断文件名代码块中进行相应注释。


ubuntu 下出现的问题

目录拖入 Terminal 后有单引号

同是 Unix,Mac 拖入却没有,其它 Linux 发行版未知。bash 中 read 读取的是字符串,所以如果存在单引号需要掐头去尾,可以用 #% 对变量进行截取。

${string#substring}:从变量 $string 的开头, 删除最短匹配 $substring 的子串。

${string%substring}:从变量 $string 的结尾, 删除最短匹配 $substring 的子串。

参考:https://blog.csdn.net/dongwuming/article/details/50605911

掐头去尾功能代码实现:

name=${name#*\'}
name=${name%\'*}

name=${${name#*\'}%\'*} 报错信息:${${name#*\'}%\'*}:错误的替换,希望知晓者评论区留言告知,感谢!

[[: not found 错误

在 ubuntu 下使用 [[]] 时,可能会报 [[: not found,这是因为 ubuntu 默认是用 dash, 而不是 bash,可以使用 sudo bash xxxx.sh 执行脚本或者将默认改为 bash。


should be written down

  1. bash (Bourne-Again Shell) 可以理解为 sh (Bourne Shell) 的升级版本,但是一开始认为 sh 就是 bash 语言的命令……然后用 sh ***.sh 执行脚本会报莫名其妙的语法错误,如 RemoveMacFile.sh: 3: Syntax error: "(" unexpected,所以执行脚本推荐用 bash ***.sh 或者 ./***.sh(需要授予权限)。

  2. .DS_Store 文件是隐藏文件,所以读取目录时需要用到 ls -a, 就会出现 “.” 和 “..” 目录,但是它们的值被 bash 认为 bad variable name。

  3. bash 有严格的语法规定,我犯得最多错的是中括号的使用。

    1. 中括号和变量之间要加空格。

    2. 单括号和双括号的区别,推荐使用双括号,更贴近平时编程习惯。

      区别详情可见 BASH 中单括号和双括号

  4. 考虑到文件夹有空格等转义字符的情况,需要在调用变量时外包双引号。


GIF 演示

Peek2020-08-3022-08


源代码

#! /bin/bash

function mac_files_del() {
    ls -a "$1" \
    | while read file;
    do
        # because of hidden file included "." and "..", they are bad variable name
        if [[ "$file" != "." &&  "$file" != ".." ]];
        then
            if [[ -d "$1/$file" ]];
            then
                if [[ "$file" = "__MACOSX" ]];
                then
                    rm -rf "$1/$file"
                    echo "$1/$file"
                else
                    mac_files_del "$1/$file"
                fi
            elif [[ "$file" = "._*" ]] || [[ "$file" =~ ".DS_Store" ]] || [[ "$file" = "Thumbs.db" ]];
            then
                rm -rf "$1/$file"
                # print path that is deleted
                echo "$1/$file"
            fi
        fi
    done
}

function mac_files_move() {
    ls -a "$1" \
    | while read file;
    do
        if [[ "$file" != "." &&  "$file" != ".." ]];
        then
            if [[ -d "$1/$file" ]];
            then
                if [[ "$file" = "__MACOSX" ]];
                then
                    mkdir -p "$move_path${1#*$dname}"
                    mv "$1/$file" "$move_path${1#*$dname}"
                else
                    mac_files_move "$1/$file"
                fi
            elif [[ "$file" = "._*" ]] || [[ "$file" =~ ".DS_Store" ]] || [[ "$file" = "Thumbs.db" ]];
            then
                # first to mkdir dir
                mkdir -p "$move_path${1#*$dname}"
                mv "$1/$file" "$move_path${1#*$dname}"
            fi
        fi
    done
}

echo "Please enter a folder to delete:"
read name
# remove the start and end char("'") of path by regex
name="${name#*\'}"
name="${name%\'*}"
# if delete, please commit the following 3 lines
# dname=$(dirname "$name")
# mkdir -p "$dname/mac_files_recover"
# move_path="$dname/mac_files_recover"

echo "------ Begin Handling Mac files ------"
# mac_files_move "$name"
mac_files_del "$name"
echo "-------------- In the end --------------"

GitHub 地址:https://github.com/dparticle/macfiles-rm

本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可。