递归地"规范化"文件名

Lan*_*nes 5 linux bash sh

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

我制作了一个脚本,可以递归重命名文件[http://pastebin.com/raw.php?i=kXeHbDQw]:

例如:之前:

THIS i.s my file (1).txt
Run Code Online (Sandbox Code Playgroud)

运行脚本后:

This-i-s-my-file-1.txt
Run Code Online (Sandbox Code Playgroud)

好.这里是:

但是:当我想"完全"测试它时,文件名如下:

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

它失败了[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
$
Run Code Online (Sandbox Code Playgroud)

所以"mv"无法处理特殊的字符..:

我工作了好几个小时..

有人有工作吗?[也可以处理2行中的字符[文件名]?]

gra*_*ity 18

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


没有特别的顺序:

  1. 您正在使用单独find查找所有目录和ls每个目录.

    1. 为什么要用for DEPTH in...如果你能做到准确一样有一个命令?

      find -maxdepth 100 -type d
      
      Run Code Online (Sandbox Code Playgroud)
    2. 这使得任意深度限制变得不必要

      find -type d
      
      Run Code Online (Sandbox Code Playgroud)
    3. 不要永远解析的输出ls,特别是如果你可以让find搞定,太

      find -not -type d
      
      Run Code Online (Sandbox Code Playgroud)
    4. 确保它在最糟糕的情况下工作:

      find -not -type d -print0 | while read -r -d '' FILENAME; do
      
      Run Code Online (Sandbox Code Playgroud)

      这会阻止read吃某些转义并使用换行符对文件名进行阻塞.

  2. 您正在为每个角色重复整个 ls | replace循环.不要 - 它会杀死表演.在每个目录中循环所有文件一次,并在一个命令中使用多个或多个替换.sedsed

    sed 's/á/a/g; s/í/i/g; ...'
    
    Run Code Online (Sandbox Code Playgroud)

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

  3. 您仍然在想ASCII:"其他特殊字符 - ASCII代码33 .. .255".别.

    1. 这些天,大多数系统在UTF-8编码,其中有一个使用Unicode 这么大一个上市出来一个变成毫无意义的-更广泛的"特"字.(甚至是多字节 - "e"是一个字节,"ė"是三个字节.)

    2. True 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"
    
    Run Code Online (Sandbox Code Playgroud)
  6. 千万不能使用egrep来检查错误.检查程序的返回代码.(就像你已经做过的那样cd.)

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

    if [[ -e $directory/$newname ]]; then
        echo "target already exists, skipping: $oldname -> $newname"
        continue
    else
        mv "$path" "$directory/$newname"
    fi
    
    Run Code Online (Sandbox Code Playgroud)
  8. 大量的sed 's/------------/-/g'调用可以更改为单个正则表达式:

    sed -r 's/-{2,}/-/g'
    
    Run Code Online (Sandbox Code Playgroud)
  9. 所述[ ]以s tr [foo] [bar]是不必要的.他们只是导致tr更换[[,并]].

  10. 真的吗?

    echo "$FOLDERNAME" | sed "s/$/\//g"
    
    Run Code Online (Sandbox Code Playgroud)

    相反怎么样?

    echo "$FOLDERNAME/"
    
    Run Code Online (Sandbox Code Playgroud)

最后,使用detox.

  • +10只是为了解决这个烂摊子.排毒量+10.不幸的是,`tr`也不处理Unicode.虽然`grep`理解等价类(`[[= a =]]`匹配'aàâãäå'),但是`sed`,`tr`或`gawk`都不会出现. (6认同)

小智 6

尝试类似的东西:

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

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

还有一个技巧:sed -e's/ - +/ - /g'将用一个" - "代替多个" - "的组.

  • 好的,这是awk和xargs的性感用法. (2认同)

Mik*_*kel 4

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

\n\n
\xc3\xa1\xc3\xad\xc3\xbc\xc5\xb1\xc3\xba\xc3\xb6\xc5\x91\xc3\xb3\xc3\xa9\xc3\x81\xc3\x8d\xc3\x9c\xc5\xb0\xc3\x9a\xc3\x96\xc5\x90\xc3\x93\xc3\x89!"#$%&\'()*+,:;<=>?@[\\]^_`{|}~\xe2\x82\xac\xe2\x80\x9a\xc6\x92\xe2\x80\x9e\xe2\x80\xa6\xe2\x80\xa0\xe2\x80\xa1\xcb\x86\xe2\x80\xb0\xc5\xa0\xe2\x80\xb9\xc5\x92\xc5\xbd\xe2\x80\x98\xe2\x80\x99\xe2\x80\x9c\xe2\x80\x9d\xe2\x80\xa2\xe2\x80\x93\xe2\x80\x94\xcb\x9c\xe2\x84\xa2\xc5\xa1\xe2\x80\xba\xc5\x93\xc5\xbe\xc5\xb8\xc2\xa1\xc2\xa2\xc2\xa3.txt\n\xc3\xa1\xc3\xad\xc3\xbc\xc5\xb1\xc3\xba\xc3\xb6\xc5\x91\xc3\xb3\xc3\xa9\xc3\x81\xc3\x8d\xc3\x9c\xc5\xb0\xc3\x9a\xc3\x96\xc5\x90\xc3\x93\xc3\x89!"#$%&\\\'()*+,:;<=>?@[]^_`{|}~\xe2\x82\xac\xe2\x80\x9a\xc6\x92\xe2\x80\x9e\xe2\x80\xa6\xe2\x80\xa0\xe2\x80\xa1\xcb\x86\xe2\x80\xb0\xc5\xa0\xe2\x80\xb9\xc5\x92\xc5\xbd\xe2\x80\x98\xe2\x80\x99\xe2\x80\x9c\xe2\x80\x9d\xe2\x80\xa2\xe2\x80\x93\xe2\x80\x94\xcb\x9c\xe2\x84\xa2\xc5\xa1\xe2\x80\xba\xc5\x93\xc5\xbe\xc5\xb8\xc2\xa1\xc2\xa2\xc2\xa3\n
Run Code Online (Sandbox Code Playgroud)\n