{"id":19167360,"url":"https://github.com/megamansec/body","last_synced_at":"2026-06-18T11:30:15.455Z","repository":{"id":221058247,"uuid":"751722730","full_name":"MegaManSec/body","owner":"MegaManSec","description":"Print the middle lines of files. It's not cat, tail, or head: it's body.","archived":false,"fork":false,"pushed_at":"2024-03-03T09:22:56.000Z","size":9,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-03T22:49:22.017Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MegaManSec.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-02-02T07:21:35.000Z","updated_at":"2024-02-06T18:54:06.000Z","dependencies_parsed_at":"2024-03-03T10:29:58.251Z","dependency_job_id":null,"html_url":"https://github.com/MegaManSec/body","commit_stats":null,"previous_names":["megamansec/body"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MegaManSec%2Fbody","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MegaManSec%2Fbody/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MegaManSec%2Fbody/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MegaManSec%2Fbody/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MegaManSec","download_url":"https://codeload.github.com/MegaManSec/body/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240247373,"owners_count":19771287,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T09:36:58.491Z","updated_at":"2026-06-18T11:30:15.255Z","avatar_url":"https://github.com/MegaManSec.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"_body_: print the middle line(s) of files.\n\n\n`body [-B \u003clines_before\u003e] [-A \u003clines_after\u003e] [-C \u003clines_before_and_after\u003e] [-n] [-N] \u003cfilename(s)\u003e`\n\nparameters:\n\n-B[number]: print _number_ lines before the middle line.\n\n-A[number]: print _number_ lines after the middle line.\n\n-C[number]: print _number_ lines before and after the middle line.\n\n-n: do not print the line number(s), just print the contents of the line(s).\n\n-N: do not print the file name (only utilized if multiple files filenames are specified).\n\nfilename: file to parse. can be specified multiple times. if multiple files are specified, the file name is also printed.\n\nby default, only the middle line is shown.\n\nexamples:\n\n```bash\n$ body /etc/passwd /etc/group\n/etc/passwd:65:_dpaudio:*:215:215:DP Audio:/var/empty:/usr/bin/false\n/etc/group:79:_atsserver:*:97:\n\n$ body -A3 -B1 /etc/passwd  /etc/group\n/etc/passwd:64:_dovecot:*:214:6:Dovecot Administrator:/var/empty:/usr/bin/false\n/etc/passwd:65:_dpaudio:*:215:215:DP Audio:/var/empty:/usr/bin/false\n/etc/passwd:66:_postgres:*:216:216:PostgreSQL Server:/var/empty:/usr/bin/false\n/etc/passwd:67:_krbtgt:*:217:-2:Kerberos Ticket Granting Ticket:/var/empty:/usr/bin/false\n/etc/passwd:68:_kadmin_admin:*:218:-2:Kerberos Admin Service:/var/empty:/usr/bin/false\n/etc/group:78:_installer:*:96:\n/etc/group:79:_atsserver:*:97:\n/etc/group:80:_lpadmin:*:98:\n/etc/group:81:_unknown:*:99:\n/etc/group:82:_lpoperator:*:100:\n\n$ body -C1 /etc/passwd\n64:_dovecot:*:214:6:Dovecot Administrator:/var/empty:/usr/bin/false\n65:_dpaudio:*:215:215:DP Audio:/var/empty:/usr/bin/false\n66:_postgres:*:216:216:PostgreSQL Server:/var/empty:/usr/bin/false\n```\n\n---\n\nbenchmarks:\n\n\ngiven the following test file:\n\n```bash\n#!/bin/bash\n\nfile=\"/var/log/auth.log.1\"\n\nbenchmark_command() {\n  local start_time=$(date +%s.%N)\n  for i in {1..20}; do\n   eval \"$1\" \u003e/dev/null\n   echo 3 \u003e /proc/sys/vm/drop_caches\n  done\n  local end_time=$(date +%s.%N)\n  local elapsed_time=$(echo \"$end_time - $start_time\" | bc -l)\n  local average_time=$(echo \"$elapsed_time / 10\" | bc -l)\n  printf \"%.6f \" \"$average_time\"\n}\necho 3 \u003e /proc/sys/vm/drop_caches\n\nbenchmark_command \"lines=\\$(wc -l \u003c $file); lines=\\$((lines/2)); head -n\\$lines $file | tail -n1\"\n\nbenchmark_command \"lines=\\$(wc -l \u003c $file); lines=\\$((lines/2)); cat -n $file | head -n\\$lines | tail -n1\"\n\nbenchmark_command \"lines=\\$(wc -l \u003c $file); lines=\\$((lines/2)); sed \\$lines,\\$lines'!d;=' $file | sed 'N;s/\\\\n/ /'\"\n\nbenchmark_command \"lines=\\$(wc -l \u003c $file); lines=\\$((lines/2)); awk 'NR==$lines{print NR\\\" \\\"\\$0}' $file\"\n\nbenchmark_command \"lines=\\$(wc -l \u003c $file); lines=\\$((lines/2)); cat -n $file | sed -n \\$lines,\\${lines}p\"\n\necho\n```\n\nexecuted 20 times, the results come out as:\n\n```bash\n for i in {1..20}; do bash /tmp/test; done  | awk '{\n    for (i = 1; i \u003c= NF; i++) {\n        sum[i] += $i\n        count[i]++\n    }\n}\nEND {\n    for (i = 1; i \u003c= NF; i++) {\n        printf \"avg %d: %.2f\\n\", i, sum[i] / count[i]\n    }\n}'\navg 1: 0.12\navg 2: 0.14\navg 3: 0.13\navg 4: 0.17\navg 5: 0.17\n```\n\n\nThe winner is clearly `head | tail`, but this isn't as useful since we want to print filenames and line numbers too, to sed it is!\n\npreviously, the script used:\n\n```bash\nawk 'NR\u003e='\"$start_line\"' \u0026\u0026 NR\u003c='\"$end_line\"' {print NR \":\" $0}' \"$filename\" 2\u003e/dev/null\n```\n\nnow it uss:\n\n```bash\nsed \"$start_line,$end_line\"'!d;=' \"$filename\" | sed 'N;s/\\n/:/' | sed \"s|^|$filename:|\"\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmegamansec%2Fbody","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmegamansec%2Fbody","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmegamansec%2Fbody/lists"}