我有几个文件夹,其中包含一些我想要重命名的文件
Foo'Bar - Title至
Title我使用的是OSX10.7。我看过其他解决方案,但没有一个能很好地解决递归问题。
有什么建议吗?
发布于 2012-07-13 03:11:29
试试这个:
ls -1 * | while read f ; do mv "$f" "`echo $f | sed 's/^.* - //'`" ; done我建议您在运行mv之前添加一个echo,以确保命令看起来正确。正如abarnert在注释中指出的那样,该命令一次只对一个目录有效。
各种命令的详细说明:
ls -1 *将为当前目录(.-files除外)中的每个文件(和目录)输出一行。因此,这将扩展到ls -1 file1 file2 ...,-1 to ls告诉它只列出文件名,并且每行一个文件。
然后,输出被输送到while read f ; ... ; done中,当read f返回零时,它将循环,直到到达文件末尾。read f从标准输入(在本例中为ls -1 ...的输出)中一次读取一行,并将其存储在指定的变量中,在本例中为f。
在while循环中,我们运行一个带有两个参数的mv命令,第一个是"$f"作为源文件(注意用引号来处理带有空格等的文件名),第二个是目标文件名,它使用sed和`(反标记)来执行所谓的命令替换,该命令替换将调用反标记内的命令,并将其替换为标准输出的输出。
echo $f | sed 's/^.* - //'通过管道将当前文件$f转换为sed,该sed将匹配正则表达式并进行替换(s/中的s ),并在标准输出上输出结果。正则表达式是^.* -,它将匹配字符串^的开头(称为锚定),然后匹配任何字符.*,后跟-,并将其替换为空字符串(//之间的字符串)。
发布于 2012-07-13 05:02:54
你的问题有两个部分:找到要递归操作的文件,并对它们进行重命名。
对于第一种情况,如果所有内容都恰好比当前目录低一个级别,那么您可以只列出当前目录中每个目录的内容(就像Mattias Wadman上面的答案一样),但更一般的情况(对于引导来说,可能更容易理解),您可以只使用find命令。
对于第二种方法,您可以使用sed并找出如何正确地使用引号和管道(您最终肯定会学到这一点),但是使用rename命令要简单得多。不幸的是,这个不是内置在Mac上的,但是你可以安装它,例如,Homebrew,或者直接下载perl脚本和sudo install -m755 rename /usr/local/bin/rename。
所以,你可以这样做:
find . -exec rename 's|[^/]* - ||' {} +如果你想做一个“预演”来确保它是正确的,添加"-n“标志来重命名:
find . -exec rename -n 's|[^/]* - ||' {} +要理解它是如何工作的,你真的应该阅读find的教程,以及重命名的手册页,但将其分解:
find .的意思是‘递归查找当前标题下的所有文件’可以添加额外的测试来过滤内容(例如,如果你想跳过除常规文件之外的所有文件,或者`- directory'.-exec标题来说并不是必需的+意味着对找到的文件进行批量处理,并传递尽可能多的文件,以代替出现在“…”中的命令中的任何{}.rename 's|[^/]* - ||' {}表示对于{}中的每个文件,将perl表达式string).[^/]* -应用于文件名,如果结果不同,则将其重命名为该s|[^/]* - ||。表示匹配正则表达式'[^/]* -‘,并将匹配替换为'’(空perl表示匹配任何以‘-’结尾的非斜杠字符组成的字符串。因此,在'./A/FooBar - Title‘中,它将匹配'FooBar -'.值得一提的是,当我有像这样复杂的事情要做时,如果几分钟后,几次尝试使用find/sed/awk/rename/etc,我仍然没有得到它,我经常只是使用Python和os.walk进行必要的编码。如果您了解Python,那么您可能更容易理解(尽管更冗长且不那么简单),并且更容易修改以适应其他用例,所以如果您感兴趣,可以提出来。
发布于 2013-04-11 03:18:38
我知道你要求批量重命名,但我建议你使用use Automator。它工作得很好,如果您将其创建为服务,您将在上下文菜单中提供以下选项:)
https://stackoverflow.com/questions/11458663
复制相似问题