将文件夹名称添加到该文件夹​​中的所有“.bin”文件

将文件夹名称添加到该文件夹​​中的所有“.bin”文件

我花了将近一天半的时间来搜索这个问题,但没有找到答案。

我希望将该文件夹的名称添加为该.bin文件夹中以 结尾的所有文件的前缀。

因此,如果文件夹的名称是,并且ABC它包含文件aa.bin、、bb.bincc.bin,那么我需要将它们重命名为ABC-aa.bin、、等。ABC-bb.binABC-cc.bin

此外,此文件夹ABC还有子文件夹,我们称之为:ABC1、、等,其中也包含文件。例如ABC2,有、、等。ABC3.binABC1aa1.binbb1.bincc1.bin

我需要该命令遍历所有文件夹并将该子文件夹的名称附加到其中的文件。因此,aa1.bin将是ABC1-aa1.bin,依此类推。

目录结构:

.
└── ABC
    ├── aa.bin
    ├── ABC1
    │   ├── aa1.bin
    │   └── bb1.bin
    ├── ABC2
    │   ├── aa2.bin
    │   └── bb2.bin
    ├── bb.bin
    └── cc.bin

答案1

这是一个“单行”操作,使用 shell 内置命令来操作文件名:

find . -name '*.bin' -exec sh -c 'p="${1%/*}"; f="${1##*/}"; echo mv -- "$1" "$p/${p##*/}-$f"' sh {} \;

在目标目录中测试它,echo如果结果看起来正确,则删除

例如

$ tree .
.
└── ABC
    ├── aa.bin
    ├── ABC1
    │   ├── aa1.bin
    │   └── bb1.bin
    ├── ABC2
    │   ├── aa2.bin
    │   └── bb2.bin
    ├── bb.bin
    └── cc.bin

3 directories, 7 files

然后

$ find . -name '*.bin' -exec sh -c 'p="${1%/*}"; f="${1##*/}"; echo mv -- "$1" "$p/${p##*/}-$f"' sh {} \;
mv -- ./ABC/ABC2/bb2.bin ./ABC/ABC2/ABC2-bb2.bin
mv -- ./ABC/ABC2/aa2.bin ./ABC/ABC2/ABC2-aa2.bin
mv -- ./ABC/aa.bin ./ABC/ABC-aa.bin
mv -- ./ABC/bb.bin ./ABC/ABC-bb.bin
mv -- ./ABC/ABC1/bb1.bin ./ABC/ABC1/ABC1-bb1.bin
mv -- ./ABC/ABC1/aa1.bin ./ABC/ABC1/ABC1-aa1.bin
mv -- ./ABC/cc.bin ./ABC/ABC-cc.bin

看起来不错,因此删除echo并再次运行

$ find . -name '*.bin' -exec sh -c 'p="${1%/*}"; f="${1##*/}"; mv -- "$1" "$p/${p##*/}-$f"' sh {} \;

给予

$ tree .
.
└── ABC
    ├── ABC1
    │   ├── ABC1-aa1.bin
    │   └── ABC1-bb1.bin
    ├── ABC2
    │   ├── ABC2-aa2.bin
    │   └── ABC2-bb2.bin
    ├── ABC-aa.bin
    ├── ABC-bb.bin
    └── ABC-cc.bin

3 directories, 7 files

答案2

您可以使用findbasename和命令来执行此操作。例如,像在这个简单的脚本中dirnamemv

#!/bin/bash

for f in $(find ABC -name '*.bin'); 
do 
  filename="$(basename $f)" 
  dir="$(dirname $f)"
  lastdir="$(basename $dir)"
  newname="$lastdir-$filename"
  newpath="$dir/$newname"
  mv $f $newpath
done

这里我使用 find 递归查找.binABC 中的所有文件,然后遍历它们并提取最后一个文件夹名称。然后构造新路径并将文件移动到同一目录但使用新名称。

编辑
为了执行此脚本,请将其内容复制到某个文件中。假设文件名为renameFiles.sh。然后使其可执行:

chmod +x renameFiles.sh

此后,您可以使用 执行它./renameFiles.sh。请注意,放置此文件的文件夹应与您的 ABC 文件夹所在的文件夹相同。

renameFiles.sh
ABC
  aa.bin
  bb.bin
  ABC1
    aa1.bin
    etc.

答案3

使用rename

shopt -s globstar
rename -n '(! -f $_ || ! /.bin$/) && next; $" = "/"; my @f = split("/"); $f[@f-1] =~ s/^/$f[@f-2]-/; $_ = "@f"' **
  • shopt -s globstar:如果设置,文件名扩展上下文中使用的模式“**”将匹配所有文件以及零个或多个目录和子目录。如果模式后跟“/”,则仅匹配目录和子目录。
  • rename -n '! -f $_ && next; $" = "/"; my @f = split("/"); $f[@f-1] =~ s/^/$f[@f-2]-/; $_ = "@f"' **:执行下列操作的试运行。对于通配符生成的每个文件名**:如果文件不是常规文件或文件名不以 结尾.bin,则跳至下一个文件名;将输出字段分隔符设置为/;根据 拆分文件名/;将倒数第二个字段添加到-最后一个字段的前面;将新文件名分配给默认变量 ( $_)。

如果结果是预期的,请-n从命令中删除该选项rename

$ tree
.
└── ABC
    ├── aa.bin
    ├── ABC1
    │   ├── aa1.bin
    │   └── bb1.bin
    ├── ABC2
    │   ├── aa2.bin
    │   └── bb2.bin
    ├── bb.bin
    └── cc.bin

3 directories, 7 files
$ rename -n '(! -f $_ || ! /.bin$/) && next; $" = "/"; my @f = split("/"); $f[@f-1] =~ s/^/$f[@f-2]-/; $_ = "@f"' **
Exiting subroutine via next at (eval 4) line 1.
rename(ABC/aa.bin, ABC/ABC-aa.bin)
Exiting subroutine via next at (eval 4) line 1.
rename(ABC/ABC1/aa1.bin, ABC/ABC1/ABC1-aa1.bin)
rename(ABC/ABC1/bb1.bin, ABC/ABC1/ABC1-bb1.bin)
Exiting subroutine via next at (eval 4) line 1.
rename(ABC/ABC2/aa2.bin, ABC/ABC2/ABC2-aa2.bin)
rename(ABC/ABC2/bb2.bin, ABC/ABC2/ABC2-bb2.bin)
rename(ABC/bb.bin, ABC/ABC-bb.bin)
rename(ABC/cc.bin, ABC/ABC-cc.bin)

相关内容