【问题标题】:Shell script for re-naming folders and subfiles用于重命名文件夹和子文件的 Shell 脚本
【发布时间】:2016-07-22 12:31:11
【问题描述】:

早安,

我需要将 786 个文件夹移动到另一个位置,每个文件夹中至少有 1 个文件。这些文件夹中的大多数确实在我需要它们移动的位置具有相同的命名文件夹,并且它们内部确实具有相同的命名文件。例如,必须移动文件夹 33。文件夹层次结构如下所示:/33/1.TIF。在我需要移动此文件夹的位置是同一个文件夹,其中包含相同的命名文件。如果我尝试将这个文件夹移到那里,它们会相互冲突。所以我需要避开它。
我有一个 CSV 文件,其中包含文件夹的旧名称和新名称。我是 linux 和 shell 本身的新手,所以我真的不知道从哪里开始。

【问题讨论】:

  • 从这里开始stackoverflow.com/questions/4286469/… 是个好主意。如果您从未做过任何 bash 编程,那么教程可能会有所帮助。
  • 首先,复制一些源目录和目标目录。学习一些 shell 命令以及如何将它们与管道运算符结合使用。尝试使用这一小部分文件和文件夹,以避免 (1) 覆盖重要文件和/或 (2) 在目标目录中创建大量冗余副本。
  • 在我们提供帮助之前,我们需要知道您是要覆盖同名的目标文件,还是要保留现有的目标文件并将新文件移动到具有后缀的相同位置,例如/33/1.TIF_001?
  • 我一直认为您问题的答案是“mv”。您的问题意味着您正在尝试做的是将“/a/b/c/THE_DIR”重命名为“/a/b/c/THE_DIR2”,mv 会这样做。如果您尝试将“/a/b/c/THE_DIR”移动到“/d/e/f/THE_DIR”,然后假设“/d/e/f”存在并且您有权限,那么 mv 将再次起作用。如果要将“/a/b/c/THE_DIR”移动到“/a/b/c/d/THE_DIR”,则需要确保“a/b/c/d”存在。
  • @DavidC.Rankin 假设我有 2 个文件夹 - OLD 和 NEW。在 OLD 我有一个名为 1 的文件夹,其中包含文件 1.TIF、2.TIF。文件夹 NEW 具有相同的文件夹,其中包含相同的文件。我希望将 OLD 1 中的文件移至 NEW 1 并重命名为 3.TIF、4.TIF

标签: linux bash shell


【解决方案1】:

有多种方法可以合并目录。难点在于检查target目录中是否已经存在同名文件,然后增加source文件的名称,避免覆盖target。

鉴于您的命名约定 #.TIF,完成此操作的一种方法是扫描 target 目录中的文件并确定 max #。您还需要扫描 文件,以解决源文件在目标中不存在的情况。

如果你有一组文件的max #,你只需遍历每个文件,检查它是否已经存在,如果存在,将文件从当前的#移动到目标目录中的# + max。如果文件不存在,只需移动它。这同样适用于目标目录结构中尚不存在的源目录 - 只需移动它即可。

将所有部分放在一起,您可以执行类似于以下的操作,其中脚本将old 目录名称、new 目录名称和ext(默认为TIF)作为参数:

#!/bin/bash

[ -z "$1" -o -z "$2" ] && {     ## validate 2 arguments given
    printf "error: insufficient input, usage: %s old new\n" "${0##*/}"
    exit 1
}

old="$1"    ## assign arguments to 'old' and 'new' (readability)
new="$2"
ext="${3:-TIF}"

[ -d "$old" -a -d "$new" ] || { ## validate both old/new are directories
    printf "error: invalid input.\n"
    [ -d "$old" ] || printf "  '%s' is not a directory.\n" "$old"
    [ -d "$new" ] || printf "  '%s' is not a directory.\n" "$new"
    exit 1
}

while read -r dname; do                 ##  for each old directory
    max=0                               ##  zero max
    nname="${dname/$old/$new}"          ##  generate new dir name 
    if [ -d "$nname" ]; then            ##  check if new dir exists, if so

        ## get max file # in old & new
        for i in "$dname"/*; do         ##  for each file in old
            [ -f "$i" ] || continue     ##  skip if not file
            fn="${i%.$ext}"             ##  get the number
            fn=${fn#${dname}/}
            ((fn > max)) && max=$fn     ##  update max if greater
        done

        for i in "$nname"/*; do         ##  do the same for new dir
            [ -f "$i" ] || continue
            fn="${i%.$ext}"
            fn=${fn#${nname}/}
            ((fn > max)) && max=$fn
        done

        ## move files from old to new
        for i in "$dname"/*; do         ##  for each file in old
            [ -f "$i" ] || continue
            newfn="${i/$old/$new}"      ##  form new file name
            if [ -f "$newfn" ]; then    ##  check if it exists, if so
                fn="${i%.$ext}"
                fn=${fn#${dname}/}      ##  add max to number and mv
                printf "mv %s %s\n" "$i" "${newfn%/*}/$((fn + max)).$ext"
                mv "$i" "${newfn%/*}/$((fn + max)).$ext"
            else                        ##  otherwise, just mv
                printf "mv %s %s\n" "$i" "$newfn"
                mv "$i" "$newfn"
            fi
        done
    else    ## if no new dir exists, move old new
        printf "mv %s %s\n" "$dname" "$nname"
        mv "$dname" "$nname"
    fi
done < <(find "$old" -type d)

例如,如果您有以下新旧目录结构:

$ tree old
old
├── 22
│   ├── 1.TIF
│   ├── 2.TIF
│   ├── 3.TIF
│   └── 4.TIF
├── 23
│   ├── 1.TIF
│   ├── 2.TIF
│   ├── 3.TIF
│   ├── 4.TIF
│   └── 5.TIF
└── 24
    ├── 1.TIF
    └── 2.TIF

$ tree new
new
├── 22
│   ├── 1.TIF
│   ├── 2.TIF
│   └── 3.TIF
└── 23
    ├── 1.TIF
    ├── 2.TIF
    └── 3.TIF

该脚本会产生以下结果(您可以删除printf 语句,或将输出重定向到/dev/null 以隐藏文本)

$ bash mvoldnew.sh old new
mv old/24 new/24
mv old/22/1.TIF new/22/5.TIF
mv old/22/2.TIF new/22/6.TIF
mv old/22/3.TIF new/22/7.TIF
mv old/22/4.TIF new/22/4.TIF
mv old/23/1.TIF new/23/6.TIF
mv old/23/2.TIF new/23/7.TIF
mv old/23/3.TIF new/23/8.TIF
mv old/23/4.TIF new/23/4.TIF
mv old/23/5.TIF new/23/5.TIF

现在new 目录树包含以下内容:

$ tree new
new
├── 22
│   ├── 1.TIF
│   ├── 2.TIF
│   ├── 3.TIF
│   ├── 4.TIF
│   ├── 5.TIF
│   ├── 6.TIF
│   └── 7.TIF
├── 23
│   ├── 1.TIF
│   ├── 2.TIF
│   ├── 3.TIF
│   ├── 4.TIF
│   ├── 5.TIF
│   ├── 6.TIF
│   ├── 7.TIF
│   └── 8.TIF
└── 24
    ├── 1.TIF
    └── 2.TIF

如果您有任何问题,或者我误解了您的说明,请查看并告诉我。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-03
    • 2015-07-13
    • 2011-06-19
    • 2014-05-01
    • 2011-04-20
    • 2015-10-12
    • 2014-01-06
    相关资源
    最近更新 更多