recursion地“规范化”文件名

我的意思是摆脱特殊字符的文件名等

我已经做了一个脚本,可以recursion重命名文件[http://pastebin.com/raw.php?i=kXeHbDQw]:

例如:之前:

THIS is my file (1).txt 

运行脚本之后:

 This-is-my-file-1.txt 

好。 这里是:

但是:当我想要“完全”testing它,像这样的文件名:

 ¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÂÃÄÅÆÇÈÊËÌÎÏÐÑÒÔÕ×ØÙUÛUÝÞßàâãäåæçèêëìîïðñòôõ÷øùûýþÿ.txt áíüűúöőóéÁÍÜŰÚÖŐÓÉ!"#$%&'()*+,:;<=>?@[\]^_`{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ''“”•–—˜™š›œžŸ¡¢£.txt 

它失败[http://pastebin.com/raw.php?i=iu8Pwrnr]:

 $ sh renamer.sh directorythathasthefiles mv: cannot stat `./áíüűúöőóéÁÍÜŰÚÖŐÓÉ!"#$%&\'()*+,:;<=>?@[]^_`{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ''“”•–—˜™š›œžŸ¡¢£': No such file or directory mv: cannot stat `./áíüűúöőóéÁÍÜŰÚÖŐÓÉ!"#$%&\'()*+,:;<=>?@[]^_`{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ''“”•–—˜™š›œžŸ¡¢£': No such file or directory mv: cannot stat `./áíüűúöőóéÁÍÜŰÚÖŐÓÉ!"#$%&\'()*+,:;<=>?@[]^_`{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ''“”•–—˜™š›œžŸ¡¢£': No such file or directory mv: cannot stat `./áíüűúöőóéÁÍÜŰÚÖŐÓÉ!"#$%&\'()*+,:;<=>?@[]^_`{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ''“”•–—˜™š›œžŸ¡¢£': No such file or directory mv: cannot stat `./áíüűúöőóéÁÍÜŰÚÖŐÓÉ!"#$%&\'()*+,:;<=>?@[]^_`{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ''“”•–—˜™š›œžŸ¡¢£': No such file or directory mv: cannot stat `./áíüűúöőóéÁÍÜŰÚÖŐÓÉ!"#$%&\'()*+,:;<=>?@[]^_`{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ''“”•–—˜™š›œžŸ¡¢£': No such file or directory mv: cannot stat `./áíüűúöőóéÁÍÜŰÚÖŐÓÉ!"#$%&\'()*+,:;<=>?@[]^_`{|}~€‚ƒ„…†....and so on $ 

所以“mv”不能处理特殊的字符..:\

我工作了很多小时

有人有工作吗? [也可以在这两行处理字符[文件名]?]

Solutions Collecting From Web of "recursion地“规范化”文件名"

mv处理特殊字符就好了。 你的脚本没有。


没有特别的顺序:

  1. 您正在使用find查找所有目录,并分别指向每个目录。

    1. 为什么for DEPTH in...使用for DEPTH in...如果你能用一个命令完全一样的话?

       find -maxdepth 100 -type d 
    2. 这使得任意的深度限制是不必要的

       find -type d 
    3. 永远不要分析ls的输出, 特别是如果你能find处理的话

       find -not -type d 
    4. 确保它在最坏的情况下工作:

       find -not -type d -print0 | while read -r -d '' FILENAME; do 

      这会停止read某些转义字符和使用换行符窒息文件名。

  2. 你正在重复整个 ls | replace ls | replace 每个单个字符的循环。 不要 – 它会杀死性能。 在每个目录中循环一次所有文件,并在一个sed命令中使用多个sed或多个替换。

     sed 's/á/a/g; s/í/i/g; ...' 

    (我打算建议sed 'y/áí/ai/' ,但不幸的是,这似乎不适用于Unicode。也许perl -CS -Mutf8 -pe 'y/áí/ai/'会。)

  3. 你还在用ASCII码思考: “其他特殊字符 – ASCII码33 .. 255” 。 别。

    1. 现在,大多数系统都使用UTF-8编码的Unicode,它具有更广泛的“特殊”字符 – 如此之大以至于逐一列出它们变得毫无意义。 (甚至是多字节 – “e”是一个字节,“ė”是三个字节。)

    2. 真正的ASCII有128个字符。 您目前所想到的是ISO 8859字符集(有时称为“ANSI”) – 特别是ISO 8859-1。 但是它们一直到8859-16,只有“ASCII”部分保持不变。

  4. echo -n $(command)是无用的。

  5. 有更简单的方法来找到给定路径的目录和基本名称。 例如,你可以做

     directory=$(dirname "$path") oldnname=$(basename "$path") # filter $oldname mv "$path" "$directory/$newname" 
  6. 不要使用egrep来检查错误。 检查程序的返回码。 (就像你已经用cd做的。)

  7. 而不是过滤掉其他错误,做…

     if [[ -e $directory/$newname ]]; then echo "target already exists, skipping: $oldname -> $newname" continue else mv "$path" "$directory/$newname" fi 
  8. sed 's/------------/-/g'调用的吨可以改为一个单一的正则表达式:

     sed -r 's/-{2,}/-/g' 
  9. tr [foo] [bar]中的[ ] s是不必要的。 他们只是让tr代替[ to,and ] to ]

  10. 真的吗?

     echo "$FOLDERNAME" | sed "s/$/\//g" 

    这个怎么样?

     echo "$FOLDERNAME/" 

最后,使用detox

尝试像这样:

 find . -print0 -type f | awk 'BEGIN {RS="\x00"} { printf "%s\x00", $0; gsub("[^[:alnum:]]", "-"); printf "%s\0", $0 }' | xargs -0 -L 2 mv 

使用xargs(1)将确保每个文件名都完全作为一个参数传递。 awk(1)用于在旧版本之后添加新的文件名。

还有一个窍门:sed -e's / – + / – / g'将会用一个“ – ”替代多个“ – ”。

假设你的脚本的其余部分是正确的,你的问题是你正在使用read但你应该使用read -r 。 注意反斜杠是如何消失的:

 áíüűúöőóéÁÍÜŰÚÖŐÓÉ!"#$%&'()*+,:;<=>?@[\]^_`{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ''“”•–—˜™š›œžŸ¡¢£.txt áíüűúöőóéÁÍÜŰÚÖŐÓÉ!"#$%&\'()*+,:;<=>?@[]^_`{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ''“”•–—˜™š›œžŸ¡¢£ 

啊…

清理脚本的一些提示:

**使用sed可以同时在多个角色上进行翻译,这样可以清理所有内容并使其更易于管理:

 dev:~$ echo 'áàaieeé!.txt' | sed -e 's/[áàã]/a/g; s/[éè]/e/g' aaaieee!.txt 

**而不是重命名每个更改的文件,运行所有的过滤器,然后做一个动作

 $ NEWNAME='áàaieeé!.txt' $ NEWNAME="$(echo "$NEWNAME" | sed -e 's/[áàã]/a/g; s/[éè]/e/g')" $ NEWNAME="$(echo "$NEWNAME" | sed -e 's/aa*/a/g')" $ echo $NEWNAME aieee!.txt 

**而不是做一个ls | read ... ls | read ...循环,使用:

 for OLDNAME in $DIR/*; do blah blah blah done 

**将你的路径遍历和重命名逻辑分隔成两个脚本。 一个脚本查找需要重命名的文件,一个脚本处理单个文件的规范化。 一旦你学习了“查找”命令,你会意识到你可以折腾第一个脚本:)