在bash / terminal中批量重命名文件夹及其文件

时间:2015-01-14 22:01:15

标签: bash terminal rename mv

我正在尝试使用命令“mv”批量重命名文件夹及其各自的文件,但它不是很顺利,我希望将文件夹重命名为:

1/
2/
3/

在保留文件扩展名的同时,还应重命名每个文件夹中的文件。

1.png
2.gif
3.jpg

非常感谢你的帮助

2 个答案:

答案 0 :(得分:2)

编辑:更好地使用函数而不是对同一脚本进行递归调用。

希望我得到所有角落案件。它以递归方式下降到目录中以处理深层嵌套的目录树。

警告:由于脚本注意不要覆盖现有文件,因此在某些极端情况下编号中可能会出现间隙 - 如果目录中存在文件0.txt并且在该文件中处理了第一个文件目录是.txt文件,它将被移动到1.txt。如果处理的第一个文件是0.txt,也会发生这种情况,因此运行脚本两次将更改编号,再次运行将更改它。

所以这是代码:

#!/bin/bash

handle_directory() {
    local counter=0

    for i in *; do
        # if the file is a directory (but not a symlink),
        #  handle it before moving
        if [ -d  "$i" ] && ! [ -h "$i" ]; then
            cd "$i"
            handle_directory
            cd ..
        fi

        # extract suffix
        suffix="${i##*.}"

        if [ "$suffix" != "$i" ]; then
            extension=".$suffix"
        else
            # If there is no filename extension, the counter
            # is the whole filename. Without this, we'd get
            # 0.Makefile and suchlike.
            extension=""
        fi

        # find a filename that isn't already taken
        # this may lead to gaps in the numbering.
        while dest="$counter$extension" && [ -e "$dest" ]; do
            let ++counter
        done

        echo mv "$i" "$dest"
        let ++counter
    done
}

# if a parameter was given, go there to handle it.
# otherwise handle the local directory. 
if ! [ -z "$1" ] && ! cd "$1"; then
    echo "Could not chdir to directory $1"
    exit -1
fi

handle_directory

一般的想法是深度优先搜索有问题的目录树。像任何树一样,目录树最好以递归方式处理,并且该函数基本归结为:遍历此目录中的所有内容,如果它们是目录,则下载并处理它,然后找到适当的文件名并重命名该事物是否它是一个目录。

使用的东西:

local counter=0 # declares a function-local variable counter and initializes it
                # to 0. crucially, that it is local means that every invocation
                # of handle_directory has its own counter.
[ -d "$i" ]     # tests if "$i" is a directory
[ -h "$i" ]     # tests if "$i" is a symlink
! [ ... ]       # negates the test. ! [ -h "$i" ] is true if "$i" is NOT a symlink
"${i##*.}"      # a bashism that cuts off the longest prefix that matches the pattern
[ -e "$dest" ]  # tests if "$dest" exists
$1              # the first parameter with which the script is called
[ -z "$1" ]     # tests if "$1" is an empty string
! cd "$1"       # descends into the directory "$1". true if that failed.

阅读以便进一步理解的手册:

man test
man bash # that's the big one.

答案 1 :(得分:1)

是单级目录吗?或者你有子目录吗?

这样的东西?

<强>之前

.
├── folderE
│   ├── conf.properties
│   ├── omg.avi
│   └── test-diff.diff
├── folder_a
│   ├── first.png
│   ├── main.jpg
│   └── second.gif
├── folder_d
│   ├── another.zip
│   └── one.mpeg
└── with space
    └── file with spaces too.mov

<强>命令:

countDir=1
for dir in *; do
  cd "$dir"; 
  countFile=1

  for file in *; do 
    mv "$file" $countFile.${file#*.}
    ((countFile++))
  done

  cd ..
  mv "$dir" $countDir
  ((countDir++))
done

或者,在同一行中相同:

countDir=1; for dir in *; do cd "$dir"; countFile=1; for file in *; do mv "$file" $countFile.${file#*.}; ((countFile++)); done; cd ..; mv "$dir" $countDir; ((countDir++)); done

<强>后:

.
├── 1
│   ├── 1.properties
│   ├── 2.avi
│   └── 3.diff
├── 2
│   ├── 1.png
│   ├── 2.jpg
│   └── 3.gif
├── 3
│   ├── 1.zip
│   └── 2.mpeg
└── 4
    └── 1.mov

重要提示:请注意,这只是一个快速而肮脏的解决方案,并且没有检查已经命名的文件/导演&#34; 1&#34; &#34; 2&#34;等