递归重命名当前目录中文件路径的某些部分

时间:2018-08-19 20:28:10

标签: bash find file-rename

假设我有以下目录树:

.
|-- foo
`-- foodir
    |-- bardir
    |   |-- bar
    |   `-- foo
    |-- foo -> bardir/foo
    `-- foodir
        |-- bar
        `-- foo

3 directories, 6 files

如何将所有foo重命名为buz,包括符号链接?喜欢:

.
|-- buz
`-- buzdir
    |-- bardir
    |   |-- bar
    |   `-- buz
    |-- buz -> bardir/buz
    `-- buzdir
        |-- bar
        `-- buz

3 directories, 6 files

我认为乍一看相对容易,但事实证明这是出乎意料的困难。

首先,我尝试使用mv对所有文件进行git ls-files

$ for file in $(git ls-files '*foo*'); do mv "$file" "${file//foo/buz}"; done

这给了我很多错误,他们说我必须先创建新目录:

mv: cannot move 'foodir/bardir/bar' to 'buzdir/bardir/bar': No such file or directory
mv: cannot move 'foodir/bardir/foo' to 'buzdir/bardir/buz': No such file or directory
mv: cannot move 'foodir/foo' to 'buzdir/buz': No such file or directory
mv: cannot move 'foodir/foodir/bar' to 'buzdir/buzdir/bar': No such file or directory
mv: cannot move 'foodir/foodir/foo' to 'buzdir/buzdir/buz': No such file or directory

我不想在复制后清理空目录,所以我尝试find -exec期望它可以在根据文件名查找文件时处理文件重命名。

$ find . -path .git -prune -o -name '*foo*' -exec bash -c 'mv "$0" "${0//foo/buz}"' "{}" \;

但是find似乎仍尝试从重命名的路径重命名文件。

find: ./foodir: No such file or directory

我的最终解决方案是为每个find命令使用mv第一个文件/目录。

#!/bin/bash

# Rename file paths recursively
while :; do
    path=$(find . -path .git -prune -o -name '*foo*' -print -quit)

    if [ -z "$path" ]; then
        break
    fi

    if ! mv "$path" "${path/foo/buz}"; then
        break
    fi
done

# Change symlink targets as well
find . -path .git -prune -o -type l -exec bash -c '
    target=$(readlink "$0")
    if [ "$target" != "${target//foo/buz}" ]; then
        ln -sfn "${target//foo/buz}"
    fi
' "{}" \;

这有点la脚,但按我的预期工作。所以我的问题是:

  1. 我可以假设find总是在其子目录/文件之前输出目录吗?
  2. 是否有机会避免多次使用find

谢谢。

0 个答案:

没有答案