菜鸟科技网

parallel命令如何高效并行处理任务?

什么是 parallel

parallel 是一个 shell 脚本工具,它允许你轻松地并行执行其他命令,你可以把它想象成一个“超级 xargs”,因为它不仅能做到 xargs 能做的事情,而且在并行处理、参数替换、错误处理等方面做得更好、更灵活。

parallel命令如何高效并行处理任务?-图1
(图片来源网络,侵删)

它的核心思想是:将标准输入的数据流分割成多个小块,然后分配给多个并行的进程去处理。


为什么使用 parallel?(与 xargs 的对比)

假设你有一个包含 1000 个文件名的列表,需要对每个文件执行一个耗时操作(如压缩、转码、下载等)。

  • 使用 xargs (串行):

    cat filelist.txt | xargs -I {} command {}

    这会一个接一个地处理 1000 个文件,非常慢。

    parallel命令如何高效并行处理任务?-图2
    (图片来源网络,侵删)
  • 使用 xargs (并行):

    cat filelist.txt | xargs -P 8 -I {} command {}

    xargs 也可以并行,但功能相对有限。

  • 使用 parallel (并行):

    cat filelist.txt | parallel -j 8 command {}

    parallel 在并行处理方面更强大、更智能,语法也更简洁直观。

    parallel命令如何高效并行处理任务?-图3
    (图片来源网络,侵删)

parallel 的主要优势:

  1. 智能并行: 默认会尝试使用所有可用的 CPU 核心 (-j +0)。
  2. 更好的输入处理: 可以自动识别行、空格、制表符等作为分隔符,比 xargs-d 选项更灵活。
  3. 丰富的替换字符串: 使用 作为占位符,功能比 xargs-I 更强大,你可以使用 {1}, {2} 来引用参数, 会自动替换为整行。
  4. 强大的组合和生成功能: 可以从输入行生成多个参数,甚至可以组合多个输入行来生成一个命令。
  5. 进度显示和控制: 可以显示进度条 (--bar)、控制任务提交速率 (--delay)、限制内存使用 (--memfree)。
  6. 内置的替换和引用: 可以轻松修改输入参数,如大写转换 ()、文件扩展名替换 (, )。
  7. 错误处理和重试: 可以指定失败时的重试次数 (--retries)。

安装 parallel

parallel 通常不在 Linux 系统的默认最小安装中,但非常容易安装。

  • Debian / Ubuntu:

    sudo apt-get install parallel
  • RHEL / CentOS / Fedora:

    sudo yum install parallel
    # 或者对于较新的版本
    sudo dnf install parallel
  • macOS (使用 Homebrew):

    brew install parallel

安装完成后,建议运行一下初始化命令,它会下载一些额外的数据并设置 ~/.parallel/will-cite 文件,以符合其许可协议(通常不影响使用)。

# 这会创建一个引用文件,表明你同意使用 parallel
parallel --citation

parallel 的基本语法和常用选项

parallel 的基本结构是:

cat input.txt | parallel [选项] [命令] [占位符]

或者直接处理文件:

parallel [选项] [命令] [占位符] ::: 参数1 参数2 参数3 ...

核心选项

选项 全称 描述 示例
-j --jobs 指定并行任务的数量。+0 表示使用所有可用核心。 parallel -j 4 echo {} ::: 1 2 3 4 5 6 7 8
占位符,代表从输入中读取的一行。 cat files \| parallel wc {}
{1}, {2} 代表命令行参数的第1、2个部分。 parallel echo {1} is in {2} ::: A B C ::: /tmp /var
用于分隔输入源,可以并列使用多个。 parallel echo {1} {2} ::: a b c ::: 1 2 3
表示选项的结束,当输入数据可能以 开头时很有用。 parallel -- -v {} ::: file1 file2
--dry-run 只打印将要执行的命令,但不实际执行。 cat files \| parallel --dry-run rm {}
--bar 显示一个进度条,非常直观。 find . -type f \| parallel --bar gzip {}
--colsep 指定输入列的分隔符,类似于 awk-F parallel --colsep ',' echo {1} is from {2} ::: data.csv
将 之后的参数都当作普通参数,防止被 parallel 误认为是选项。 parallel -- -k echo {} ::: -a -b -c

实用示例

示例 1:最简单的并行处理

目标: 对 1 到 10 的数字进行平方计算。

# 方法1:使用 ::: 传递参数
parallel echo {}^2 ::: 1 2 3 4 5 6 7 8 9 10
# 方法2:从文件中读取
seq 10 > numbers.txt
parallel echo {}^2 :::: numbers.txt  # :::: 表示从文件读取

解释: parallel 会为 110 中的每一个数字都启动一个 echo {}^2 进程。 会被替换成当前的数字。

示例 2:并行处理文件列表

目标: 压缩当前目录下所有的 .log 文件。

# 查找所有 .log 文件,并并行执行 gzip 命令
find . -name "*.log" | parallel gzip {}
# 或者更安全的写法,使用 -- 确保文件名不会被当作选项
find . -name "*.log" | parallel -- gzip {}

**解释:find 命令将每个 .log 文件的路径通过管道传给 parallel, 被替换为文件路径,gzip 命令被并行执行。

示例 3:使用多个输入源(笛卡尔积)

目标:a, b, c 分别与 1, 2, 3 组合并打印。

parallel echo {1} on {2} ::: a b c ::: 1 2 3

输出:

a on 1
a on 2
a on 3
b on 1
b on 2
b on 3
c on 1
c on 2
c on 3

解释: 分隔了两个参数列表。parallel 会生成所有可能的组合。

示例 4:处理 CSV 文件

目标: 读取一个 CSV 文件,并打印每行的第一列和第三列。

假设 data.csv 内容如下:

name,age,city
Alice,30,New York
Bob,25,Los Angeles
Charlie,35,Chicago

命令:

# 默认分隔符是逗号
parallel --colsep , echo "Name: {1}, City: {3}" :::: data.csv

输出:

Name: name, City: city
Name: Alice, City: New York
Name: Bob, City: Los Angeles
Name: Charlie, City: Chicago

解释: --colsep , 告诉 parallel 用逗号来分割输入行。{1} 指代第一列,{3} 指代第三列。

示例 5:强大的文件名替换

parallel 提供了许多有用的替换字符串,类似于 basenamedirname 命令。

假设文件列表为 path/to/file1.txt, path/to/file2.log

替换符 描述 示例输入 示例输出
完整输入 path/to/file.txt path/to/file.txt
文件名(带扩展名) path/to/file.txt file.txt
目录名 path/to/file.txt path/to
文件名(不带扩展名) path/to/file.txt file
去掉最后一个扩展名 path/to/file.tar.gz path/to/file.tar
去掉所有扩展名 path/to/file.tar.gz path/to/file

目标: 将当前目录下所有 .jpg 文件转换为 .png 文件,并保留原始目录结构。

# 假设文件在 subfolder/ 中
find . -name "*.jpg" | parallel convert {.}.jpg {.}.png

解释: 对于输入 ./subfolder/image.jpg

  1. ./subfolder/image.jpg
  2. ./subfolder/image
  3. 命令变为 convert ./subfolder/image.jpg ./subfolder/image.png

示例 6:组合多个输入行生成一个命令

这是一个高级功能,非常强大,可以使用 --link--xapply

目标: 从一个文件读取用户名,从另一个文件读取密码,然后创建用户。

假设 users.txt

alice
bob
charlie

假设 passwords.txt

pass123
secret456
secure789

命令:

# --xapply 会将两个列表的对应元素配对
parallel --xargs -n 2 --link sudo useradd -p {2} {1} :::: users.txt passwords.txt

解释:

  • 表示从两个文件读取输入。
  • --link 会将两个输入源(users.txtpasswords.txt)的对应行配对。
  • {1} 代表第一个输入源(users.txt)的当前行。
  • {2} 代表第二个输入源(passwords.txt)的当前行。
  • --xargs -n 2 确保每次只取两行输入(一个用户名,一个密码)。

parallel 是一个能极大提升你在命令行工作效率的“神器”,无论是处理日志、批量重命名文件、进行数据转换还是并行下载,它都能让你的脚本运行得更快、更简洁。

学习建议:

  1. 从简单的例子开始,parallel echo {} ::: a b c
  2. 熟练掌握 和 的用法,这是最核心的功能。
  3. 学习使用 --colsep 处理结构化数据。
  4. 探索文件名替换符 , , ,它们在文件批处理中非常实用。
  5. --dry-run--bar 这两个调试和监控利器。

一旦你掌握了 parallel,你可能会发现自己很少再想用 xargs 了。

分享:
扫描分享到社交APP
上一篇
下一篇