【问题标题】:Search and replace using prename or sed使用 prename 或 sed 搜索和替换
【发布时间】:2016-07-03 11:01:09
【问题描述】:

我正在尝试在文件名中执行搜索和替换,如下所示:

$ 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' ./*

在重命名命令中使用上述正则表达式,我们可以将基本名称组转换为大写,我想知道如何将该组中的下划线替换为空格。

PS:另外我知道你们中的一些人可能会说这是一个重复的问题,但请再读一遍,在提出这个问题之前我已经研究了很多,在任何地方都找不到这个特定的问题。

【问题讨论】:

  • 请解释与您的答案一起使用的任何正则表达式。
  • 帮助别人在文件名中添加空格是不道德的。
  • @webb,好的,然后用破折号替换下划线:)
  • @webb:虽然我也尽量避免使用空格,但仍然没有不正确转义的借口。
  • @tom idk 学习正则表达式与请求单行脚本有什么关系(您的问题的解决方案显然不是 1 个正则表达式!)但我只是告诉您为什么要one-liner 通常被认为是负面的,我看到你现在已经删除了这个要求,祝你好运!

标签: bash sed file-rename


【解决方案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-split 可防止目录与其子目录一起重命名。一次只能重命名叶文件/目录。
  • 在需要允许文件名(包括传入文件名)中包含空格的地方引用所有内容。

【讨论】:

    【解决方案2】:
    #!/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
    

    【讨论】:

    • 如果名称可能包含空格,您必须像这样引用mv 调用:mv "$NAME" "$NEW_NAME"。此外,此 find 调用可能不适用于空格。
    • 很公平。我绝不提倡空间。我相信@webb 说得最好!
    • 在 mv 和 -print0 中添加了引号以供查找。
    • 添加 -print0 无济于事。始终使用find ...|| while IFS= read -r file 而不是for file in $(find...),然后您可以查看-print0 等。
    猜你喜欢
    • 2014-09-13
    • 2015-01-04
    • 1970-01-01
    • 2012-07-08
    • 1970-01-01
    • 1970-01-01
    • 2010-11-05
    • 2018-11-16
    相关资源
    最近更新 更多