如何批量重命名目录、子目录和文件?

How to batch rename directories, subdirectories, and files?

我有一个 MRI 图像数据集,包含在目录(每个主题一个;超过 200 个主题)和多个子目录(用于结构、功能和 RS 数据,每个包含更多子目录)中,其中包含来自的文件扫描。其中一些目录和文件包含主题编号 (sub-001 > structural > sub-001_T1_structural > sub-001_T1_structural.nii.gz)。

由于此预先存在的数据取自 3 项独立的研究,因此部分参与者人数存在重叠。我需要的是将所有包含主题编号的文件夹和文件重命名为从 500 开始的数字序列(以避免与原始数据集重叠)。所以我想要的 sub-001 输出是 sub-501 > structural > sub-501_T1_structural > sub-501_T1_structural.nii.gz。本质上,我需要将每个参与者的主题编号更改为从 501 开始的序列。我不能简单地向每个主题编号添加 500,因为某些主题已被排除在外,因此数字串中存在间隙(例如从子跳转011 到子 013).

目前我已经尝试过这个简短的脚本,它适用于每个单独的主题,但我想不出一种方法可以同时将它应用于所有主题:

find . -depth -name "*sub-001*" | \
while IFS= read -r ent; do mv $ent ${ent%sub-001*}sub-501${ent##*sub-001}; done

对于任何错误、误解或基本错误,我深表歉意 -- 我对脚本编写完全陌生,所以我必须自己弄清楚才能完成我的分析。

编辑: 代码更改为最近的编辑

编辑: 为清楚起见添加了上下文

我尝试将此命令应用于包含原始主题编号的每个目录(加上子目录和文件),并使用正确的重命名主题编号(例如 sub-001 > sub-501,sub-002 > sub-502 , sub-003 > sub-503 等):

    for a in 001 002 003 004 005 006 007 008 009 010 011 013 014 015
 016 017 018 019 020 021 022 023 024 026 027 028 029 030 031 032 034
 036 037 038 039 045 046 047 049 050 051 052 053 054 055 056 057 058
 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075
 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092
 093 094 095 096 097 098 099 100 101 102 104 105 106 107 109 110 111
 112 113 114 115 116 117 118 119 120
    
    for b in 501 502 503 504 505 506 507 508 509 510 511 512 513 514
 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599
 600 601 602 603 604 605 606 607 608
    
    find . -depth -name "*sub-${a}*" | \
    while IFS= read -r ent; do mv $ent ${ent%sub-${a}*}sub-${b}${ent##*sub-${a}}; done

但是我遇到了错误:line 7: syntax error near unexpected token 'for'。有没有办法按顺序将命令应用于每个主题,并确保重命名的文件夹和文件按照上面的尝试从 501 向上顺序跟随?

您需要 dofor 之后但在循环体之前,但您也可能只需要一个循环,而不是两个嵌套循环。是这样的吗?

i=501
for a in sub-[0-9][0-9][0-9]; do
    ((i++))
    b=sub-$i
    find . -depth -name "*sub-${a}*" | \
    while IFS= read -r ent; do
        dest="${ent%sub-${a}*}sub-${b}${ent##*sub-${a}}"
        mkdir -p "${dest%/*}"
        mv "$ent" "$dest"
    done
done

(( ... ))表达式是数学整数表达式求值;我们只需将 i 的先前值加一,然后通过在结果前添加 sub- 来创建 b 的新值。

这会循环遍历当前目录中的 sub-[0-9][0-9][0-9] 值,根据您的规范应该得到您想要的内容,而无需显式枚举所有这些值。

如果目标目录不存在,这会创建目标目录,但会留下空的源目录。如果要重命名目录,则需要稍微复杂一些的方法(首先对目录中的文件进行重命名,然后重命名目录树中向上移动的目录),但目前这可能足够简单明了。如果您需要重复执行此操作,完全自动化可能会很有意义。

while read 显然不适用于包含换行符的文件名。 find ... -exec sh -c '...' _ {} + 是一种更优雅、更健壮的解决方案,但这可能是在您更熟悉基础知识的时候使用的。