使用prename或sed搜索和替换

时间:2016-07-03 11:01:10

标签: bash sed file-rename

我正在尝试执行搜索并在文件名中替换如下:

$ tree
.
├── a_a
│   ├── a_b_c
│   ├── a b c.mkv
│   ├── b_b
│   └── b_c_d
├── b_a
│   ├── a_f_r
│   ├── c_d
│   ├── f_r_e
│   └── r r
├── c_r
│   ├── d_f
│   └── r_a_s.mkv
└── d.mkv

我想用空格替换文件和文件夹名称中的下划线。我想要这样做的方法是首先替换内部目录中存在的文件和文件夹的基本名称中的下划线,然后向上移动,以便我在下一次迭代中仍然存在我正在递归的路径,因为如果我重命名上层目录,在下一次迭代中,访问其内部目录和文件的路径将变为无效。

我知道我可以使用find命令对文件进行递归。现在我想使用一个工具来执行替换操作,从内部文件开始然后向外移动。我在编写正则表达式方面没有太多经验,但我认为我们可以使用正则表达式中的分组来做到这一点,但我不太确定这么大的帮助。

直到现在我已经能够弄清楚我们可以使用正则表达式组来访问文件名的某些部分。更具体地说,我们可以使用以下正则表达式获取文件夹和文件的基本名称:

rename -n 's!([^/]*\Z)!uc($1)!e' ./*

在rename命令中使用上面的regex,我们可以将基本名称组转换为大写,我想知道如何将该组中的下划线替换为空格。

PS:我也知道有些人可能会说这是一个重复的问题,但请再次阅读,我在提出问题之前已经进行了很多研究,并且无法在任何地方找到这个具体问题。

2 个答案:

答案 0 :(得分:1)

#!/bin/bash

# man find, search for -type
#
# these are other types:
# b - block special, c - character special, d - directory, p - named pipe
# f - regular file, l - symbolic link, s - socket

# Move directories first, then everything else
for TYPE in d f; do

    for NAME in $( find . -type $TYPE -print0 ); do
        if [[ $NAME =~ [a-z] ]]; then
            NEW_NAME=$NAME
            NEW_NAME=${NEW_NAME//[\_]/-} # Change '-' to ' ' if you insist on spaces
            echo "renaming '$NAME' to '$NEW_NAME'"
            mv "$NAME" "$NEW_NAME"
        fi
    done

done

答案 1 :(得分:1)

#!/bin/bash
find -depth | while IFS= read -r fn; do
    pnew=$(dirname  "$fn") 
    fnew=$(basename "$fn") 
    if [[ "$fnew" =~ "_" ]]; then
        new="$pnew/${fnew//_/ }"
        echo "$fn -> $new"  
        mv "$fn" "$new"
    fi
done

说明:

  • -depth参数让 find 遍历深度优先的目录。
  • dirname / basename - 拆分可防止目录与其子项一起重命名。一次只能重命名叶子文件/目录。
  • 在需要的地方引用所有内容以允许文件名中的空格(包括传入的文件名)。