1

我正在尝试编写一个 bash 脚本来删除空格、下划线和点并用破折号替换它们。我还设置为小写并删除括号。这是(长)第二个 sed 命令,它似乎有效。

第一个 sed 调用使​​用带有 '\' 的空格来转义原始名称,就像我制表符完成时一样,这就是我认为的问题。

如果我用'echo'替换'mv -i',我会得到我想要的:原始文件名用反斜杠转义,然后是新名称。如果我将它粘贴到终端它可以工作,但是在脚本中使用 mv 时,空格会导致问题。逃避是行不通的。

#!/bin/bash

for a in "$@"; do
    mv -i $(echo "$a" | sed -e 's/ /\\\ /g') $(echo "$a" | sed -e 's/\(.*\)/\L\1/' -e 's/_/-/g' -e 's/ /-/g' -e 's/---/--/g' -e 's/(//g' -e 's/)//g' -e 's/\[//g' -e 's/\]//g' -e 's/\./-/g' -e 's/-\([^-]*\)$/\.\1/')
done

另一种解决方案是在名称周围加上引号,但我不知道该怎么做。我觉得我已经接近了,但我很难过。

我也考虑过“重命名”命令,但您不能像使用 sed 那样执行多个操作。

请指出任何其他问题,这是我的第一个脚本之一。我不确定我的“$@”或“$a”位是否完全正确。

干杯。

编辑:

示例输入文件名

I am a Badly [named] (file) - PLEASE.rename_me.JPG

应该成为

i-am-a-badly-named-file--please-rename-me.jpg 

edit2:我的解决方案,从 gniourf_gniourf 非常有用的纯 bash 答案调整:

#!/bin/bash
for a in "$@"; do
    b=${a,,}                       #lowercase
    b=${b//[_[:space:]\.]/-}       #subst dot,space,underscore with dash
    b=${b//---/--}                 #remove triple dash
    b=${b//[()\[\]]/}              #remove brackets
    if [ "${b%-*}" != "$b" ]; then #if there is a dash (prevents filename.filename)
        b=${b%-*}.${b##*-}         #replace final dash with a dot for extension
    fi                           
    if [ "$a" != "$b" ]; then      #if there has been a change
        echo '--->' "$b"           #
        #mv -i -- "$a" "$b"        #rename
    fi
done

仅当文件有空格等且没有扩展名(例如this BAD_filename变为this-bad.filename. 但这些是媒体文件并且应该有扩展名时,这才会失败,所以无论如何我都必须对它们进行排序。

再次欢迎更正和改进。我是新手

4

2 回答 2

4

尝试这样做rename

rename 's/[_\s\.]/-/g' *files

shell提示。它非常有用,如果需要,您可以在其中放入一些代码。

当您的测试有效时,您可以移除-n(试运行模式开关)。

警告 还有其他同名的工具可能会也可能不会这样做,所以要小心。

如果您运行以下命令 ( linux)

$ file $(readlink -f $(type -p rename))

你有一个像

.../rename: Perl script, ASCII text executable

那么这似乎是正确的工具=)

如果不是,则使其成为默认值(通常已经如此)Debian和衍生,例如Ubuntu

$ sudo update-alternatives --set rename /path/to/rename

(替换/path/to/rename为您的perl's rename命令的路径。


最后但同样重要的是,这个工具最初是由 Perl 的父亲 Larry Wall 编写的。

于 2013-10-29T19:32:14.033 回答
0

只是为了记录,看:

$ a='I am a Badly [named] (file) - PLEASE.rename_me.JPG'
$ # lowercase that
$ echo "${a,,}"
i am a badly [named] (file) - please.rename_me.jpg
$ # Cool! let's save that somewhere
$ b=${a,,}
$ # substitution 's/[_ ]/-/g:
$ echo "${b//[_ ]/-}"
i-am-a-badly-[named]-(file)---please.rename-me.jpg
$ # or better, yet:
$ echo "${b//[_[:space:]]/-}"
i-am-a-badly-[named]-(file)---please.rename-me.jpg
$ # Cool! let's save that somewhere
$ c=${b//[_[:space:]]/-}
$ # substitution 's/---/--/g' (??)
$ echo "${c//---/--}"
i-am-a-badly-[named]-(file)--please.rename-me.jpg
$ d=${c//---/--}
$ # substitution 's/()[]//g':
$ echo "${d//[()\[\]]/}"
i-am-a-badly-named-file--please.rename-me.jpg
$ e="${d//[()\[\]]/}"
$ # substitution 's/\./-/g':
$ echo "${e//\./-}"
i-am-a-badly-named-file--please-rename-me-jpg
$ f=${e//\./-}
$ # substitution 's/-\([^-]*\)$/\.\1/':
$ echo "${f%-*}.${f##*-}"
i-am-a-badly-named-file--please-rename-me.jpg
$ # Done!

现在,这是您要实现的目标的 100% bash 实现:

#!/bin/bash
for a in "$@"; do
    b=${a,,}
    b=${b//[_[:space:]]/-}
    b=${b//---/--}
    b=${b//[()\[\]]/}
    b=${b//\./-}
    b=${b%-*}.${b##*-}
    mv -i -- "$a" "$b"
done

是的,完成!

所有这些标准都被称为shell 参数扩展

评论。对于更健壮的脚本,您可以检查 a 是否具有扩展名(阅读:其名称中的句点),否则算法的最后替换会失败一点。为此,请将以下行放在for语句的正下方:

[[ a != *.* ]] && { echo "Oh no, file \`$a' has no extension..."; continue; }

*.*(这条线的部分不是很可爱吗?)

于 2013-10-29T21:29:20.640 回答