例如,如果我要移动一组文件名为Chapter1_sectionX 到特定文件夹,例如 book/chapter1和Chapter2_sectionX 到书/chapter2等等。我目前正在使用这种方法,我发现它效率低下:
touch chapter{1,2}_section{1..4}.odf
mkdir -p book/chapter{1,2}
mv chapter1_section* book/chapter1
mv chapter2_section* book/chapter2
有没有更短的方法来做到这一点而不使用为了环形?
答案1
不使用for
循环?您可以使用 perlrename
实用程序(在某些发行版上也称为prename
、 或file-rename
或perl-rename
)来创建子目录并将文件重命名到其中。例如:
$ rename -v 'BEGIN{mkdir "book"};
if (m/chapter(\d+)/) {
my $d="book/chapter$1";
mkdir $d;
$_ = "$d/$_"
}' *
chapter1.txt renamed as book/chapter1/chapter1.txt
chapter2.txt renamed as book/chapter2/chapter2.txt
chapter3.txt renamed as book/chapter3/chapter3.txt
chapter4.txt renamed as book/chapter4/chapter4.txt
chapter5.txt renamed as book/chapter5/chapter5.txt
剧本英文摘要:
如果当前文件名 ( $_
) 与正则表达式匹配chapter(\d+)
,则从文件名中提取章节编号(即$1
,这是正则表达式中的第一个也是唯一的捕获组,(\d+)
),为该章节创建一个目录,然后将当前文件重命名为目录。
不匹配的文件名将被忽略。
rename
如果重命名脚本更改了 .perl 的值,perl仅尝试重命名文件$_
。它还拒绝覆盖现有文件,除非您使用该-f
选项强制它。
Perl 重命名允许您使用任何重命名脚本中的 perl 代码(但请注意,编译指示use strict
已生效,因此您需要声明变量)。如果代码更改$_
,文件将被重命名。如果没有,就不会。
请注意,最好先进行一次试运行,并选择-n
确保重命名能够执行您想要的操作(从错误的批量重命名中恢复可能是一个主要的 PITA)。 -n
不重命名任何文件,它只是显示它的内容会做。将 替换-n
为-v
(如我上面的)以获得详细输出,或者仅删除-n
以获得静默操作。
答案2
我发现这个mmv
实用程序对于这样的东西很方便:
$ mmv -v 'chapter*_section*.odf' 'book/chapter#1/'
chapter1_section1.odf -> book/chapter1/chapter1_section1.odf : done
chapter1_section2.odf -> book/chapter1/chapter1_section2.odf : done
chapter1_section3.odf -> book/chapter1/chapter1_section3.odf : done
chapter1_section4.odf -> book/chapter1/chapter1_section4.odf : done
chapter2_section1.odf -> book/chapter2/chapter2_section1.odf : done
chapter2_section2.odf -> book/chapter2/chapter2_section2.odf : done
chapter2_section3.odf -> book/chapter2/chapter2_section3.odf : done
chapter2_section4.odf -> book/chapter2/chapter2_section4.odf : done
给予
$ tree book
book
├── chapter1
│ ├── chapter1_section1.odf
│ ├── chapter1_section2.odf
│ ├── chapter1_section3.odf
│ └── chapter1_section4.odf
└── chapter2
├── chapter2_section1.odf
├── chapter2_section2.odf
├── chapter2_section3.odf
└── chapter2_section4.odf
2 directories, 8 files
答案3
为了完整起见,并且由于文件和目标目录名称的简单结构,以下find
命令将迭代所有章节文件并将它们移动到名称源自文件名的目标目录:
find . -maxdepth 1 -type f -name 'chapter*_section*.odf' -exec bash -c 'f={}; d="book/${f%_*}"; mv "$f" "$d"' \;
这将(隐式)循环遍历所有匹配的文件,并执行一个 shell 命令,该命令通过从文件名中chapter*_section*.odf
删除最后一个组件来派生目标目录名称,从而有效地仅保留该部分。然后它将当前处理的文件移动到 下相应的子目录中。_*
chapterN
book/
笔记
- 该
-maxdepth 1
选项与确保仅对当前目录中的文件执行操作,而不是在处理当前目录后递归地对已移至目标目录的文件执行操作。 - 将 嵌入到名为via
{}
的 shell 命令中-exec
灰心但如果您不假设恶意代码注入尝试,则它将起作用。