Bash重命名扩展递归

Bash重命名扩展递归,bash,batch-rename,Bash,Batch Rename,我知道有很多类似的事情,但要么它们不是递归的,要么它们是巨大的 这就是我得到的: find . -name "*.so" -exec mv {} `echo {} | sed s/.so/.dylib/` \; 当我运行find部分时,它会给我一个文件列表。当我运行sed部分时,它会用.dylib替换任何.so。当我把它们放在一起时,它们就不起作用了 我用echo替换mv以查看发生了什么: ./AI/Interfaces/C/0.1/libAIInterface.so ./AI/Interfa

我知道有很多类似的事情,但要么它们不是递归的,要么它们是巨大的

这就是我得到的:

find . -name "*.so" -exec mv {} `echo {} | sed s/.so/.dylib/` \;
当我运行find部分时,它会给我一个文件列表。当我运行sed部分时,它会用.dylib替换任何.so。当我把它们放在一起时,它们就不起作用了

我用echo替换mv以查看发生了什么:

./AI/Interfaces/C/0.1/libAIInterface.so ./AI/Interfaces/C/0.1/libAIInterface.so
什么都没有被替换
怎么了?

怎么了
for X in `find . -name "*.so"` 
do
 mv $X ${X/.so/.dylib}
done
只执行一次,在启动
find
之前,
sed
在其输入上给出
{}
,它与
/.so/
不匹配,并且保持不变,因此生成的命令行是 找到-名称“*.so”-exec mv{}{} 他需要递归:

echo {} | sed s/.so/.dylib/
如果你有Bash4

find . -name "*.so" -exec mv {} {}
这将正确地执行所有操作

#!/bin/bash

function walk_tree {
    local directory="$1"
    local i

    for i in "$directory"/*; 
        do
            if [ "$i" = . -o "$i" = .. ]; then 
                continue
            elif [ -d "$i" ]; then  
            walk_tree "$i"  
            elif [ "${i##*.}" = "so" ]; then
                echo mv $i ${i%.*}.dylib    
            else
                continue
            fi
        done    
}

walk_tree "."
查找-L-键入f-名称“*.so”-print0 |,而IFS=read-r-d”FNAME;做 mv--“$FNAME”“${FNAME%.so}.dylib” 完成 正确地说,我们的意思是:

1) 它将只重命名文件扩展名(由于使用了
${FNAME%.so}.dylib
)。使用
${X/.so/.dylib}
的所有其他解决方案都不正确,因为它们错误地重命名了文件名中第一个出现的
.so
(例如,
x.so.so
被重命名为
x.dylib.so
,或者更糟的是,
/libTemp.so-1.9.3/libTemp.so
被重命名为
/libTemp.dylib-1.9.3/libTemp.so
——一个错误)

2) 它将处理文件名中的空格和任何其他特殊字符(双引号除外)

3) 它不会更改目录或其他特殊文件

4) 它将跟随符号链接进入子目录并链接到目标文件,并重命名目标文件,而不是链接本身(find的默认行为是处理符号链接本身,而不是链接指向的文件)。

通常重命名文件扩展名的bash脚本 归功于

用法
  • 在例如
    /usr/bin
    中创建名为
    ext rename
    (无扩展名,因此可以像命令一样运行它)的文件(确保
    /usr/bin
    已添加到
    $PATH
  • 在终端中的任何位置运行
    ext rename[ext1][ext2]
    ,其中
    [ext1]
    正在从中重命名,而
    [ext2]
    正在重命名到中。例如:
    ext rename so dylib
    ,它将任何扩展名为
    .so
    的文件重命名为相同的名称,但扩展名为
    .dylib

  • 如果任何目录或文件名可能包含空格,请用“@Lachlan:这本身没有帮助。您必须在读取X时执行
    查找…”,而不是为
    执行
    (并执行引用)。此外,该发现应该有一个
    -类型f
    。谢谢!我应该意识到……不知怎么的……还有什么解决方案没有提到吗?喜欢这个,它工作得很好,而且很快。谢谢。太棒了!终于找到了一个真正有效的解决方案。万分感谢!
    #!/bin/bash
    
    shopt -s globstar
    shopt -s nullglob
    for file in /path/**/*.so
    do
     echo mv "$file"  "${file/%.so}.dylib"
    done
    
    find -L . -type f -name "*.so" -print0 | while IFS= read -r -d '' FNAME; do mv -- "$FNAME" "${FNAME%.so}.dylib" done
      #/bin/bash
      find -L . -type f -name '*.'$1 -print0 | while IFS= read -r -d '' file; do
          echo "renaming $file to $(basename ${file%.$1}.$2)";
          mv -- "$file" "${file%.$1}.$2";
      done