用 shell 对上万个文件批量重命名,每行一个 mv 命令,速度比较慢且 CPU 占用高,大约 70 秒跑 1000 行命令,应该跟每行开了一个进程有关,怎么避免这种情况?试了下将 1000 行 mv 写入一行并用分号分隔,没用。
1
dzdh 2021-10-22 12:28:27 +08:00
|
2
nowheretoseek OP @dzdh 不经常,只是记得 shell 脚本中分行写与并行写有些什么不同来着,想试着解决下,却不行
|
3
AoEiuV020 2021-10-22 12:32:24 +08:00
如果确定瓶颈是创建进程,就随便换个脚本语言都可以单进程直接调用系统调用重命名的,
|
4
nowheretoseek OP @AoEiuV020 是的,python 脚本或者写个 sublimetext 插件都可以解决此问题
|
5
mmtromsb456 2021-10-22 13:06:04 +08:00 via iPhone
应当试试用 rename 命令来正则重命名,应该 10k+文件重命名都是有规律的吧
|
6
ETiV 2021-10-22 13:15:58 +08:00 via iPhone
xargs 有一个 -P 参数,可以指定并发数
|
7
nowheretoseek OP @mmtromsb456 有规律,但不是容易用规则表达的那种,还是编辑器做好列表再命名省事
|
8
huntagain2008 2021-10-22 15:27:50 +08:00 1
本人非程序员。
<试了下将 1000 行 mv 写入一行并用分号分隔,没用。 $ mv xxx xxx;mv xxx xxx;mv xxx xxx 这个是一串命令列表,前面的命令先运行,后面紧跟。实际和分行是一样的 $ mv xxx $ mv xxx 如果将分号分隔那串命令两端加上圆括号,就成了进程列表,生成了子 shell 来执行对应的命令。 $ (mv xxx;mv xxx;mv xxx) "在 shell 脚本中,经常使用子 shell 进行多进程处理。但是采用子 shell 的成本不菲,会明显拖慢处理速度。在交互式的 CLI shell 会话中,子 shell 同样存在问题。它并非真正的多进程处理,因为终端控制着子 shell 的 I/O 。 在交互式的 shell CLI 中,还有很多更富有成效的子 shell 用法。进程列表、协程和管道(后续会讲到)都利用了子 shell 。它们都可以有效地在交互式 shell 中使用。在交互式 shell 中,一个高效的子 shell 用法就是使用后台模式。在讨论如何将后台模式与子 shell 搭配使用之前,你得先搞明白什么是后台模式。 在 CLI 中运用子 shell 的创造性方法之一就是将进程列表置入后台模式。你既可以在子 shell 中进行繁重的处理工作,同时也不会让子 shell 的 I/O 受制于终端。 " 那么将进程列表置入后台模式效果怎么样呢?楼主要不然试试。 $ (mv xxx; mv xxx; 搞一千次)& 或者用协程 |
9
nowheretoseek OP @huntagain2008 谢谢,我试着用这个办法重命名了 2600 个文件,用了 125 秒,之前的办法估计要用 170 秒,进步挺名显。感觉 shell 执行这个任务差不多就这样了,试了下用 python 脚本只需 1.3 秒
|
10
nowheretoseek OP python 脚本备用
``` # coding: utf-8 import shutil import time names = [x.split("\t") for x in open("names.txt", "r").read().strip().split("\n")] start = time.time() for name in names: old, new = name shutil.move(old, new) print(time.time() - start) ``` |