Bash 搜索+;替换文件名中的字符串

Bash 搜索+;替换文件名中的字符串,bash,Bash,使用bash,如何搜索目录中递归包含的所有文件名(包括文件夹)中出现的所有子字符串“foo”,并将其替换为“bar” 例如,如果当前结构看起来像: -foo_test - fooo.txt - xfoo - yfoo.h - 1foo.c 在运行bash脚本后,应该是这样的: -bar_test - baro.txt - xbar - ybar.h - 1bar.c 此处所示的两种变体均在OPs测试结构上正常工作: find .

使用bash,如何搜索目录中递归包含的所有文件名(包括文件夹)中出现的所有子字符串“foo”,并将其替换为“bar”

例如,如果当前结构看起来像:

-foo_test
    - fooo.txt
    - xfoo
        - yfoo.h
- 1foo.c
在运行bash脚本后,应该是这样的:

-bar_test
    - baro.txt
    - xbar
        - ybar.h
- 1bar.c

此处所示的两种变体均在OPs测试结构上正常工作:

find . -depth -name '*foo*' -execdir bash -c 'mv -i "$1" "${1//foo/bar}"' bash {} \;
或者,如果您有大量文件,并希望它运行得更快:

find . -depth -name '*foo*' -execdir bash -c 'for f; do mv -i "$f" "${f//foo/bar}"; done' bash {} +

编辑:如评论中所述,我先前使用的
查找
命令(未使用
execdir
选项)和
重命名
在重命名名称中包含foo的目录中的文件时遇到问题。正如所建议的,我已经将find命令更改为使用
-execdir
,并且我已经使用
rename
命令删除了这个变体,因为它是一个非标准命令。

这很棘手,因为目录名中有多个“foo”实例。当您将
/foo\u test/xfoo
更改为
/bar\u test/xbar
时,
/foo\u test
中的所有内容都将无法访问。所以我先更改了文件名,然后更改了目录名中最后出现的“foo”。我添加了echo语句来跟踪开发过程中发生的事情。当然,你可以删除它们

#!/bin/sh
#first change the file names
#append '.' to process files in current directory
for D in $(find -d . -name "*foo*" -type d ) '.' 
do 
    pushd $D >> /dev/null
    echo 'directory: ' "$D"
    for file in $(find . -name "*foo*" -type f -maxdepth 1)
    do
        echo '    change' "$file" 'to' `echo "$file" | sed s/foo/bar/g`
        mv "$file" `echo "$file" | sed s/foo/bar/g`
    done
    popd >> /dev/null
done

echo ''

#Now change the directory names
for D in $(find -d . -name "*foo*" -type d )
do 
    echo 'change' "$D" 'to' `echo "$D" | sed 's/\(.*\)foo/\1bar/'`
    #change only the last occurance of foo
    mv "$D" `echo "$D" | sed 's/\(.*\)foo/\1bar/'`
done
我毫不怀疑有更简短、更优雅的方法可以做到这一点(可能只需删除脚本中的一半行),但我非常确定这是可行的


编辑 相同的环是一面红旗。这个版本只循环一次。您在尝试
mv.'.'.
时收到一条消息,但它被安全地忽略了

#!/bin/sh
#first change the file names
#append '.' to change file in current directory
for D in $(find -d . -name "*foo*" -type d ) '.' 
do 
    pushd $D >> /dev/null
    echo 'directory: ' "$D"
    for file in $(find . -name "*foo*" -type f -maxdepth 1)
    do
        echo '    change' "$file" 'to' `echo "$file" | sed s/foo/bar/g`
        mv "$file" `echo "$file" | sed s/foo/bar/g`
    done
    popd >> /dev/null

    echo 'change' "$D" 'to' `echo "$D" | sed 's/\(.*\)foo/\1bar/'`
    #change only the last occurence of foo
    mv "$D" `echo "$D" | sed 's/\(.*\)foo/\1bar/'`
done

... 假设您有
rename
命令,这是非标准的。如果他可以多次使用foo,您不需要在正则表达式中使用
g
?(即
s/foo/bar/g
)@triplee-更糟糕的是,我看到在不同的发行版上安装了两种不同的不兼容变体可以缩短为
作为“$@”
。我会使用
-execdir
,因为它既更安全,又因为
mv path/foo/more/path/foo.txt path/bar/more/path/bar.txt
不起作用。有关更多想法,请参阅。@SSTeve:但我发现最初尝试在不使用
-execdir
的情况下使用
rename
失败,因此我已将其从我的答案中删除。您是否需要两次担心包含foo的文件?e、 g.将foo-foo.txt重命名为bar-bar.txt