在Bash中根据父目录重命名文件

3

我会尝试将之前的帖子串联起来,以完成此任务。 目录树如下:

TEST
   |ABC_12345678
       3_XYZ
   |ABC_23456789
       3_XYZ
   etc

每个名为“TEST”的父文件夹中的每个文件夹始终以ABC_\d{8}开头,其中8个数字始终不同。在文件夹ABC_\d{8}中,始终有一个名为3_XYZ的文件夹,其中始终有一个名为“MD2_Phd.txt”的文件。目标是使用在ABC文件夹名称中找到的特定8位数字ID重命名每个“MD2_PhD.txt”文件,即“\d{8}_PhD.txt”。
在各种帖子的不同代码上进行了几次迭代后,这是我能想出的最好的代码。
cd /home/etc/Desktop/etc/TEST
find -type d -name 'ABC_(\d{8})' |
find $d -name "*_PhD.txt" -execdir rename 's/MD2$/$d/' "{}" \;
done

“3_XYZ”文件夹对于所有文件来说,名称是否总是静态的? - RomanPerekhrest
是的,该文件夹在ABC中始终命名为3_XYZ。 - jnorth
find将接受多个目录作为起点,因此find $( find -type d -name 'ABC_(\d{8})' ) -name "*_PhD.txt" -execdir rename 's/MD2$/$d/' "{}" \;(无需done)可能有效,除非您的文件或目录名称中有未显示的空格。 没有时间测试。其他答案看起来稍微更简单;-)。祝好运。 - shellter
2个回答

2

您正在将find的输出导入到另一个find中。这样做是行不通的。

请改用循环:

dir_re='^.+_([[:digit:]]{8})/'
for file in *_????????/3_XYZ/MD2_PhD.txt; do
  [[ -f $file ]] || continue
  if [[ $file =~ $dir_re ]]; then
    dir_num="${BASH_REMATCH[1]}"
    new_name="${file%MD2_PhD.txt/$dir_num.txt}" # replace the MD2_PhD at the end
    echo mv "$file" "$new_name"                 # remove echo from here once tested
  fi
done

1
非常出色,运行得非常顺畅!非常感谢!! - jnorth
1
太好了,它起作用了!当有人回答我的问题时我该怎么做? - codeforester

2

find + bash 解决方案:

find -type f -regextype posix-egrep -regex ".*/TEST/ABC_[0-9]{8}/3_XYZ/MD2_Phd\.txt" \
-exec bash -c 'abc="${0%/*/*}"; fp="${0%/*}/";
 mv "$0" "$fp${abc##*_}_PhD.txt" ' {} \;

查看结果:

$ tree TEST/ABC_*
TEST/ABC_12345678
└── 3_XYZ
    └── 12345678_PhD.txt
TEST/ABC_1234ss5678
└── 3_XYZ
    └── MD2_Phd.txt
TEST/ABC_23456789
└── 3_XYZ
    └── 23456789_PhD.txt

一开始我没看到这个,不知道为什么...我也会尝试这个方法,谢谢@RomanPerekhrest。 - jnorth
1
非常好的解决方案!谢谢你们两个——这两种方法将对其他出现的问题进行微调非常有帮助。 - jnorth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接