我正在寻找一种简单的方法来重命名 Synology NAS 上的许多文件。找到 和sed
可用,但不可用rename
。
我可以使用以下命令获取这些文件和文件夹的列表
find . \( -type d -name "@*" -prune \) -o \( -name "**" \) -print
上述 find 语句显示所有包含“/”字符的文件,在 Synology bash 中替换为“”。
我需要替换的所有特殊字符是:
/ \ : ? ' ’ ´ ’
根据所使用的平台和文件共享协议,这些字符看起来会有所不同,显示也会有所不同,或者根本不显示,或者会导致不同类型的问题。我可以通过以下方式在 Synology bash 中找到这些字符:
-name "**" -o -name '*\\*' -o -name "*:*" -o -name "*\?*" -o -name "*\'*" -o -name "*´*" -o -name "*`*"
如何替换它找到的每个文件和目录中的这些字符?我将从字符“/”开始。
非常感谢您的帮助!
加里
答案1
假设该find
命令与您要重命名的文件集完全匹配,并且您要重命名为“安全”文件名。在不知道文件名中的确切字符的情况下,我只能提供建议,但这里有两个。
删除奇怪的字符。这预设了该字符可以通过
bash
替换来本地处理find . -depth \( -type d -name "@*" -prune \) -o \( -name "**" -execdir \ bash -c 'echo "Processing $PWD"; for f; do echo mv -- "$f" "${f///}"; done' _ {} + \)
仅保留已知字符。确保其中
tr
包含您想要保留的字符集。find . -depth \( -type d -name "@*" -prune \) -o \( -name "**" -execdir \ bash -c 'echo "Processing $PWD"; for f; do echo mv -- "$f" "$(tr -cd '[:alnum:][:punct:][:space:]' <<<"$f")"; done' _ {} + \)
在这两种情况下,请删除echo
以将调试转换为活动语句。
答案2
这是使用 for 循环的替代方案:
# Option globstar activates the ** (search recursivelly).
# Option nullglob removes an * when it matches no file/dir.
$ shopt -s globstar nullglob
$ for i in **/*; do
# if the name of the file matches the pattern
# perform the `mv` command
[[ "$(basename "$i")" =~ ^@.*$ ]] && \
mv -- "$i" "$(echo "$i" | sed -e 's;^@;;' -e 's;/@;/;')"
[[ "$(basename "$i")" =~ ^**$ ]] && \
mv -- "$i" "$(echo "$i" | sed 's;;;')"
done
注意:在执行移动/删除命令之前最好先进行备份。
答案3
如果您的 find 命令给出了您想要的结果,您可以将其通过管道传输到 sed,然后从 sed 传输到 bash(或重定向到文件,而不是通过管道传输到 bash/ash):
find . \( -type d -name "@*" -prune \) -o \( -name "**" \) -print | sed -n 's/\(.*\)\(\)\(.*\)/mv '"'&'"' '"'\1\3'"'/p' | bash
- 你的 find 命令将列出你想要的文件和目录
- sed 将遍历所有行,替换/删除特殊字符并将每一行设置为 bash/ash (mv) 执行。
或者您可以将 sed 重定向到文件并 bash/ash 该文件(bash list_of_files_and_dirs_to_be_renamed)。在实际数据上使用它之前,请在不重要的文件/目录上进行良好的测试。