2010-01-31 126 views
12

我知道有很多这样的事情,但它们不是递归地工作,或者它们是巨大的。Bash重命名扩展递归

这是我得到:

find . -name "*.so" -exec mv {} `echo {} | sed s/.so/.dylib/` \; 

当我运行它给我的文件列表中找到部分。当我运行sed部分时,它会用.dylib替换任何.so。当我将它们一起运行时,它们不起作用。

我取代MV回声看看发生了什么:

./AI/Interfaces/C/0.1/libAIInterface.so ./AI/Interfaces/C/0.1/libAIInterface.so 

没有被替换了!
有什么不对?

回答

24

这将尽一切正确

 
find -L . -type f -name "*.so" -print0 | while IFS= read -r -d '' FNAME; do 
    mv -- "$FNAME" "${FNAME%.so}.dylib" 
done 

通过正确,我们的意思是:

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

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

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

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

+0

太棒了!最后一个解决方案,实际工作。谢谢百万! – antred 2014-05-23 12:21:50

3
for X in `find . -name "*.so"` 
do 
mv $X ${X/.so/.dylib} 
done 
+0

如果任何一个目录名或文件名可能包含空格,请用“。 – 2010-01-31 15:18:30

+1

@Lachlan”引用这两个mv的参数:这本身并不会帮助您,您必须执行'find ... | while read read X '而不是'for'(并且做引用)。另外,这个查找应该有一个'-type f'。 – 2010-01-31 16:46:16

+1

[为什么你不应该解析ls(1)的输出](http:// mywiki .wooledge.org/ParsingLs) – slhck 2013-05-12 17:42:31

3

什么是错的是,

 
echo {} | sed s/.so/.dylib/ 
只执行一次,则推出了 find之前, sed是在它的输入,这不符合 /.so/和保持不变,所以你得到的命令行给出 {}
 
find . -name "*.so" -exec mv {} {} 

+0

谢谢!我应该已经意识到......不知何故......任何解决方案还没有提及? – Pepijn 2010-02-01 16:31:18

0

他需要递归:

#!/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 "." 
1

如果你有击4

#!/bin/bash 

shopt -s globstar 
shopt -s nullglob 
for file in /path/**/*.so 
do 
echo mv "$file" "${file/%.so}.dylib" 
done 
4

bash脚本来重命名文件扩展名通常

#/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 

aps2012

用法
  1. 创建一个文件例如例如ext-rename(没有扩展名,所以你可以像命令一样运行)。 /usr/bin其中[ext1]从重命名和[ext2]被重命名为(确保/usr/bin被添加到您的$PATH
  2. 运行ext-rename [ext1] [ext2]在终端,随时随地。一个示例使用将是:ext-rename so dylib,它将使用扩展名.so将任何文件重命名为相同名称,但扩展名为.dylib
+0

爱这个,它的工作原理,它很快,谢谢你。 – 2014-01-12 21:44:45