在名称中使用双引号批量重命名文件

时间:2017-01-09 11:25:43

标签: linux bash sed find

我有一个文件系统,其中包含许多我想在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将文件名传递给执行的三个命令来理解转义。庆典。是否可以创建一个以这种方式删除双引号和单引号的命令?

1 个答案:

答案 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作为去限制器分开。