我有一个文件系统,其中包含许多我想在Windows机器上使用的文件。文件名中的非法字符是个问题,因此我搜索了一个bash命令,该命令以递归方式清除所有文件中的非法字符。
我找到了这个解决方案(https://stackoverflow.com/a/19009177/7394134):
find . -name "*[<>:\\|?*]*" -exec bash -c 'x="{}"; y=$(sed "s/[<>:\\|?*]\+/-/g" <<< "$x") && mv "$x" "$y" ' \;
它适用于大多数文件,但它不适用于包含双引号的文件,并且失败并显示以下错误消息:
bash :(双引号后的其余文件名):找不到命令
我发现了一些略有不同的问题,例如“删除包含双引号的文件”或“删除文件中带有sed的双引号”,但遗憾的是我无法将其解决方案转移到上述命令的成功修改。
备注:即使可能有更简单的单行(我很乐意看到它们!),我想通过-exec将文件名传递给执行的三个命令来理解转义。庆典。是否可以创建一个以这种方式删除双引号和单引号的命令?
答案 0 :(得分:0)
一种方法是在涉及command-substitution bash
的{{1}}中适当地双引所有操作,即$(..)
。不这样做让shell将执行的命令结果(如果结果有空格/特殊字符)视为单独的单词。如果在结果上运行任何命令,则由于参数不正确而导致错误(在您可能的情况下,可能是由于对变量y
的分配不正确)
下面是一个简单的技巧,双引用sed
命令,如
find . -name "*[<>:\\|?*]*" -exec bash -c 'x="{}"; y="$(sed "s/[<>:\\|?*]\+/-/g" <<< "$x")" && mv "$x" "$y" ' \;
可以帮到你。
或者,如果您对以更简单的方式处理名称中包含特殊字符的文件感兴趣,
使用-print0
中的GNU find
选项,使用bash
process-substitution处理文件名中包含特殊字符/空格的文件。正确的脚本将是
#!/bin/bash
while IFS= read -r -d $'\0' file
do
newfile="$(sed "s/[<>:\\|?*]\+/-/g" <<< "$file")"
mv -v -- "$file" "$newfile"
done <(find . -name "*[<>:\\|?*]*" -print0)
-print0 (a GNU find specific option)
在NULL
命令返回的每个文件/目录的末尾附加一个find
字符,以便处理带有空格/特殊字符和read
的名称(-d$'\0'
),将find
的输出与\ 0作为去限制器分开。