用于文件名跨平台兼容性的 Shell 脚本

用于文件名跨平台兼容性的 Shell 脚本

我正在尝试创建一个 shell 脚本,通过文件管理器的上下文菜单运行,以对某些文件名进行某些替换,这些文件名在跨不同平台(Linux、MacOS、Windows 等)传输时可能会导致问题。

到目前为止,我已经用我的初学者级别的脚本编写技能成功获得了以下(可能相当脏)代码,但我仍在努力寻找替换这些字符的方法:''“”/(当我使用这些智能单和双引号,以及像其他 sed 表达式一样的斜杠,文件将被删除!)。

我遇到的另一个问题是该脚本无法删除文件名之前的空格,尽管它在直接在终端中输入时可以工作。

我希望能得到一些帮助来找到解决方案。

for filename in "${@}"; do
    NEWNAME="$(echo "$filename" | sed -e 's/:/-/g' -e "s/'//g" \
    -e 's/["|?|*]//g' -e 's/[<|>]/ /g' -e 's/\\/ /g' -e 's/\[/ /g' \
    -e 's/\]/ /g' -e 's/\s\s*/ /g' -e 's/^\s\s*//g' -e 's/\s\s*\./\./g')"
    mv "$filename" "$NEWNAME"
done

答案1

只需使用perl-renamerename在 Debian 和 Ubuntu 等上找到)。首先,为了测试,让我们创建一个糟糕的名字:

touch "   a truly “horrible”, ‘awful’"$'\n'"name     with a newline and *globs*, and even a 'single' quote or two!   .txt"

看起来是这样的:

$ ls
'   a truly “horrible”, ‘awful’'$'\n''name     with a newline and *globs*, and even a '\''single'\'' quote or two!   .txt'

请注意,有一个换行符,如果您尝试循环它(糟糕),您将看到:

$ for f in *; do echo "$f"; done
   a truly “horrible”, ‘awful’
name     with a newline and *globs*, and even a 'single' quote or two!   .txt

因此,这个名字包含了您将面临的大部分(如果不是全部)问题。现在,使用rename来摆脱坏字符:

$ rename 's/[*“”‘’\n<|>"[\]]//g; s/:/-/g; s/\s+/ /g; s/^\s*//; s/\s+\././g; '"s/'//g" *
$ ls -N
a truly horrible, awfulname with a newline and globs, and even a single quote or two!.txt

正如你所看到的,这消除了你正在寻找的所有不好的东西(据我所知,因为我只有你的 sed 尝试继续)。您可以将其放入您的脚本中,如下所示:

for filename in "${@}"; do
    rename 's/[*“”‘’\n<|>"[\]]//g; 
    s/:/-/g; 
    s/\s+/ /g; 
    s/^\s*//; 
    s/\s+\././g; '"s/'//g" "$filename"
done

解释

基本语法与 非常相似sed,您使用相同的替换运算符。正则表达式是:

  • s/[*“”‘’\n<|>"[\]]//g;:将出现的所有*\n<|>"[或 `] 替换为空,然后将其删除。
  • s/:/-/g:将出现的任何空白字符(基本上是空格、制表符或换行符)替换为-
  • s/\s+/ /g:将所有出现的一个或多个连续空白字符替换为一个空格。 * s/^\s*//:删除文件名开头的所有前导空格,
  • s/\s+\././g:删除 之前出现的一个或多个空白字符.
  • "s/'//g": 删除所有单引号。请注意整个命令是如何的rename '...',然后我添加了"s/'//g".这是因为您无法转义单引号字符串中的单引号,因此我必须关闭单引号字符串并打开一个新的双引号字符串来处理字符'

另外,我没有费心去处理/,因为/with\0是文件名中唯一不允许的字符,并且您根本无法创建包含/.

相关内容