更改开头具有特定模式的目录中的文件名

时间:2015-01-25 20:07:52

标签: shell awk

我想从一个目录中删除文件名中的数字:

文件名:

89_Ajohn_text_phones
3_jpegs_directory
..

我想拥有什么

Ajohn_text_phones
jpegs_directory

我试过了:

rename 's/^\([0-9]|[0-9][0-9]\)_//g' *

但我没有工作。

2 个答案:

答案 0 :(得分:2)

有两个rename工具。您似乎尝试使用的是基于Perl,因此使用perl样式的正则表达式。逃避规则与sed略有不同;特别是,用于分组的括号不会被转义(转义括号是字面括号)。使用

rename 's/^([0-9]|[0-9][0-9])_//' *

或者,更简洁,

rename 's/^[0-9]{1,2}_//' *

rename是基于Debian的发行版(如Ubuntu)的默认设置。

另一个rename工具来自util-linux,它是一个非常简单的工具,无法与正则表达式一起使用,无法处理此特定要求。这是默认情况下,例如,基于Fedora的发行版,更糟糕的是,那些通常甚至不打包Perl重命名。您可以在CPAN上找到Perl重命名here,如果需要,可以将其放在/usr/local/bin中,但除此之外,您最简单的选项可能是mvsed的shell循环:

for f in *; do
    # set dest to the target file name
    # Note: using sed's extended regex syntax (-r) because it is nice.
    #       Much less escaping of metacharacters is needed. Note that
    #       sed on FreeBSD and Mac OS X uses -E instead of -r, so there
    #       you'd have to change that or use regular syntax, in which
    #       the regex would have to be written as ^[0-9]\{1,2\}_
    dest="$(echo "$f" | sed -r 's/^[0-9]{1,2}_//')"
    if [ "$f" = "$dest" ]; then
        # $f did not match pattern; do nothing
        true;
    elif [ -e "$dest" ]; then
        # avoid losing files.
        echo "$dest already exists!"
    else
        mv "$f" "$dest"
    fi
done

您可以将其放入shell脚本中,例如rename.sh

#!/bin/sh

transform="$1"
shift

for f in "$@"; do
    dest="$(echo "$f" | sed -r "$transform")"
    if [ "$f" = "$dest" ]; then
        ## do nothing
        true;
    elif [ -e "$dest" ]; then
        echo "$dest already exists!"
    else
        mv "$f" "$dest"
    fi
done

并致电rename.sh 's/^[0-9]{1,2}_//' *

还有一个警告:

dest="$(echo "$f" | sed -r "$transform")"

"$f"可能是echo认为是命令行选项的内容,例如-n-e。我不知道如何解决这个问题(如果你读了这个并且知道一个,请发表评论),但是如果你处于一个将自己束缚到bash不是问题的位置,你可以使用{ {1}}这里是字符串:

bash

(并将dest="$(sed -r "$transform" <<< "$f")" shebang替换为#!/bin/sh)。但是,这样的文件很少见,所以随着时间的推移,这不是一件坏事。

答案 1 :(得分:1)

#!/bin/bash
for f in *
do
  mv "$f" "${f#*_}"
done