bash脚本重命名目录中的所有文件?

时间:2009-12-24 00:47:43

标签: linux bash shell

我有一堆需要重命名的文件。

file1.txt needs to be renamed to file1_file1.txt
file2.avi needs to be renamed to file2_file2.avi

你可以看到我需要原始文件名后面的_。

这些文件很多。

8 个答案:

答案 0 :(得分:5)

到目前为止,所有答案都是:

  1. 需要一些非便携式工具
  2. 使用包含空格或换行符的文件名可怕地破解
  3. 不是递归的,即不会下降到子目录
  4. 这两个脚本解决了所有这些问题。

    Bash 2.X / 3.X

    #!/bin/bash
    
    while IFS= read -r -d $'\0' file; do
        dirname="${file%/*}/"
        basename="${file:${#dirname}}"
        echo mv "$file" "$dirname${basename%.*}_$basename"
    done < <(find . -type f -print0)
    

    Bash 4.X

    #!/bin/bash
    
    shopt -s globstar
    for file in ./**; do 
        if [[ -f "$file" ]]; then
            dirname="${file%/*}/"
            basename="${file:${#dirname}}"
            echo mv "$file" "$dirname${basename%.*}_$basename"
        fi
    done
    

    一旦您对其输出感到满意并再次运行,请务必从您选择的任何脚本中删除echo

    修改

    修复了以前版本中未正确处理路径名的问题。

答案 1 :(得分:4)

for file in file*.*
do 
    [ -f "$file" ] && echo mv "$file" "${file%%.*}_$file"
done

递归的想法

recurse() {
 for file in "$1"/*;do
    if [ -d "$file" ];then
        recurse "$file"
    else
        # check for relevant files
        # echo mv "$file" "${file%%.*}_$file"
    fi
 done
}
recurse /path/to/files

答案 2 :(得分:4)

对于您的具体情况,您希望使用mmv,如下所示:

pax> ll
total 0
drwxr-xr-x+ 2 allachan None 0 Dec 24 09:47 .
drwxrwxrwx+ 5 allachan None 0 Dec 24 09:39 ..
-rw-r--r--  1 allachan None 0 Dec 24 09:39 file1.txt
-rw-r--r--  1 allachan None 0 Dec 24 09:39 file2.avi

pax> mmv '*.*' '#1_#1.#2'

pax> ll
total 0
drwxr-xr-x+ 2 allachan None 0 Dec 24 09:47 .
drwxrwxrwx+ 5 allachan None 0 Dec 24 09:39 ..
-rw-r--r--  1 allachan None 0 Dec 24 09:39 file1_file1.txt
-rw-r--r--  1 allachan None 0 Dec 24 09:39 file2_file2.avi

您需要知道通配符匹配并不贪婪。这意味着文件a.b.txt将变为a_a.b.txt,而不是a.b_a.b.txt

mmv程序是作为我的CygWin的一部分安装的,但我必须

sudo apt-get install mmv

在我的Ubuntu盒子上让它失效。如果它不在您的标准发行版中,那么您使用的任何包管理器都希望它可用。

如果出于某种原因,您不允许安装它,则必须使用其他答案中显示的其他bash for - 循环类型解决方案之一。我更喜欢mmv我自己的简洁,但你可能没有选择。

答案 3 :(得分:2)

find . -type f | while read FN; do
  BFN=$(basename "$FN")
  NFN=${BFN%.*}_${BFN}
  echo "$BFN -> $NFN"
  mv "$FN" "$NFN"
done

答案 4 :(得分:0)

我喜欢PERL cookbook的重命名脚本。它可能不是/ bin / sh,但你可以进行正则表达式重命名。

/ bin / sh方法是使用sed / cut / awk来改变for循环中的每个文件名。如果目录很大,则需要依赖xargs。

答案 5 :(得分:0)

应该提到mmv工具,这是为此特别制作的。

这里描述:http://tldp.org/LDP/GNU-Linux-Tools-Summary/html/mass-rename.html

......以及替代品。

答案 6 :(得分:0)

我使用prename(基于perl),它包含在各种Linux发行版中。它适用于正则表达式,所以要说将所有img_x.jpg改为你要做的IMAGE_x.jpg

prename 's/img_/IMAGE_/' img*jpg

您可以使用-n标志预览更改,而不进行任何实际更改。

prename man entry

答案 7 :(得分:-1)

#!/bin/bash
# Don't do this like I did:
# files=`ls ${1}`

for file in *.*
do
if [ -f $file ];
then
newname=${file%%.*}_${file}
mv $file $newname
fi
done

这个不会重命名子目录,只会重命名常规文件。