mirror of
https://github.com/dylanaraps/pfetch.git
synced 2026-01-02 16:02:12 +01:00
Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af166966b9 | ||
|
|
219d8f2117 | ||
|
|
0834d53b2a | ||
|
|
0f1d6845db | ||
|
|
3895dd003d | ||
|
|
6c3d5c3a87 | ||
|
|
616e1b0c3b | ||
|
|
44dca45301 | ||
|
|
256c1678d6 | ||
|
|
a3bdc11167 | ||
|
|
2bc0fd87a5 | ||
|
|
8b9c409650 | ||
|
|
52617b2e6e | ||
|
|
77dce6a678 | ||
|
|
812f9ef231 | ||
|
|
87effdbc5a | ||
|
|
3f5845e20c | ||
|
|
c94e2c5d9d | ||
|
|
d8d8899ad2 | ||
|
|
1ff17055b9 | ||
|
|
d1d3b7b740 | ||
|
|
9564246e6c | ||
|
|
08d9834854 | ||
|
|
b7c7bc6c4c | ||
|
|
11d1c2e789 | ||
|
|
55408239db | ||
|
|
35ae795068 | ||
|
|
e1228975fd | ||
|
|
4d1be75c20 | ||
|
|
8d1ab2d0dd | ||
|
|
301c52dd5f | ||
|
|
0d1a340ef2 | ||
|
|
49a3db1653 | ||
|
|
d828d1e718 | ||
|
|
9963de75d5 | ||
|
|
3e58031fe0 | ||
|
|
405fc20eef | ||
|
|
133d63137c | ||
|
|
3686c06238 |
92
README.md
92
README.md
@@ -1,80 +1,42 @@
|
||||
# pfetch
|
||||
<p align="center"><img src="https://user-images.githubusercontent.com/6799467/65944518-68834d80-e421-11e9-9b14-6ca26a16108a.png" width="350px"></p>
|
||||
<h1 align="center">pfetch</h1>
|
||||
<p align="center">A pretty system information tool written in POSIX sh</p><br>
|
||||
|
||||
A pretty system information tool written in POSIX `sh`.
|
||||
<img src="https://user-images.githubusercontent.com/6799467/65945384-5bfff480-e423-11e9-863e-4e7cf16eb648.png" width="40%" align="right">
|
||||
|
||||
The goal of this project is to implement a simple system information tool in POSIX `sh` using features built into the language itself (*where possible*).
|
||||
The goal of this project is to implement a simple system
|
||||
information tool in POSIX `sh` using features built into
|
||||
the language itself (*where possible*).
|
||||
|
||||
The source code is highly documented and I hope it will act as a learning resource for POSIX `sh` and simple information detection across various different operating systems.
|
||||
The source code is highly documented and I hope it will
|
||||
act as a learning resource for POSIX `sh` and simple
|
||||
information detection across various different operating
|
||||
systems.
|
||||
|
||||
If anything in the source code is unclear or is lacking in its explanation, open an issue. Sometimes you get too close to something and you fail to see the "bigger picture"!
|
||||
If anything in the source code is unclear or is lacking
|
||||
in its explanation, open an issue. Sometimes you get too
|
||||
close to something and you fail to see the "bigger
|
||||
picture"!
|
||||
|
||||
```sh
|
||||
➜ pfetch
|
||||
___ goldie@KISS
|
||||
(.· | os KISS Linux
|
||||
(<> | host Lenovo YOGA 900-13ISK
|
||||
/ __ \ kernel 5.3.1-coffee
|
||||
( / \ /| uptime 6h 20m
|
||||
_/\ __)/_) pkgs 130
|
||||
\/-____\/ memory 1721M / 7942M
|
||||
```
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
## OS support
|
||||
|
||||
- **Linux**
|
||||
- Alpine Linux, Arch Linux, Arco Linux, Artix Linux, CentOS, Debian, Elementary, Fedora, Gentoo, Guix, Hyperbola, KISS Linux, Linux Lite, Linux Mint, Mageia, Manjaro, MX Linux, NixOS, OpenSUSE, Parabola, Pop!\_OS, PureOS, Slackware, Ubuntu and Void Linux.
|
||||
- All other distributions are supported with a generic penguin logo.
|
||||
- **Android**
|
||||
- **BSD**
|
||||
- DragonflyBSD, FreeBSD, NetBSD and OpenBSD.
|
||||
- **Windows**
|
||||
- Windows subsystem for Linux.
|
||||
- **Haiku**
|
||||
- **MacOS**
|
||||
- **Minix**
|
||||
- **Solaris**
|
||||
- **BSD**
|
||||
- DragonflyBSD
|
||||
- FreeBSD
|
||||
- NetBSD
|
||||
- OpenBSD
|
||||
- **Windows**
|
||||
- Windows subsystem for Linux.
|
||||
- **Linux**
|
||||
- Alpine Linux
|
||||
- Arch Linux
|
||||
- Arco Linux
|
||||
- Artix Linux
|
||||
- CentOS
|
||||
- Debian
|
||||
- Elementary
|
||||
- Fedora
|
||||
- Gentoo
|
||||
- Guix
|
||||
- Hyperbola
|
||||
- KISS Linux
|
||||
- Linux Lite
|
||||
- Linux Mint
|
||||
- Mageia
|
||||
- Manjaro
|
||||
- MX Linux
|
||||
- NixOS
|
||||
- OpenSUSE
|
||||
- Parabola
|
||||
- Pop!\_OS
|
||||
- PureOS
|
||||
- Slackware
|
||||
- Ubuntu
|
||||
- Void Linux
|
||||
- Other distributions are supported with a generic penguin logo.
|
||||
|
||||
## TODO
|
||||
|
||||
- [ ] Add optional and additional information detection.
|
||||
- [ ] Terminal Emulator ([#12](https://github.com/dylanaraps/pfetch/pull/12))
|
||||
- The way I implement this in `neofetch` is interesting.
|
||||
- [ ] Expand operating system support.
|
||||
- [ ] Android
|
||||
- [ ] iOS
|
||||
- [ ] AIX ([#7](https://github.com/dylanaraps/pfetch/issues/7))
|
||||
- [ ] IRIX ([#8](https://github.com/dylanaraps/pfetch/issues/8))
|
||||
- [ ] FreeMiNT ([#9](https://github.com/dylanaraps/pfetch/issues/9))
|
||||
- [ ] Windows ([#10](https://github.com/dylanaraps/pfetch/issues/10))
|
||||
- [ ] CYGWIN
|
||||
- [ ] MSYS
|
||||
- [ ] MINGW
|
||||
|
||||
## Configuration
|
||||
|
||||
|
||||
189
pfetch
189
pfetch
@@ -129,7 +129,7 @@ get_os() {
|
||||
|
||||
case $os in
|
||||
Linux*)
|
||||
# Some Linux disttributions (which are based on others)
|
||||
# Some Linux distributions (which are based on others)
|
||||
# fail to identify as they **do not** change the upstream
|
||||
# distributions identification packages or files.
|
||||
#
|
||||
@@ -154,6 +154,12 @@ get_os() {
|
||||
if command -v lsb_release; then
|
||||
distro=$(lsb_release -sd)
|
||||
|
||||
# Android detection works by checking for the existence of
|
||||
# the follow two directories. I don't think there's a simpler
|
||||
# method than this.
|
||||
elif [ -d /system/app ] && [ -d /system/priv-app ]; then
|
||||
distro="Android $(getprop ro.build.version.release)"
|
||||
|
||||
else
|
||||
# This used to be a simple '. /etc/os-release' but I believe
|
||||
# this is insecure as we blindly executed whatever was in the
|
||||
@@ -261,19 +267,6 @@ get_os() {
|
||||
IFS='(' read -r distro _ < /etc/release
|
||||
;;
|
||||
|
||||
CYGWIN*|MSYS*|MINGW*)
|
||||
# Grab everything after the first instance of
|
||||
# white-space in the command output of 'wmic'.
|
||||
#
|
||||
# The format of 'wmic' is as follows:
|
||||
# Caption=Microsoft Windows 7 Enterprise
|
||||
#
|
||||
# This extracts: ^^^^^^^^^^^^^^^^^^^^
|
||||
read -r _ distro <<-EOF
|
||||
$(wmic os get Caption /value)
|
||||
EOF
|
||||
;;
|
||||
|
||||
*)
|
||||
# Catch all to ensure '$distro' is never blank.
|
||||
# This also handles the BSDs.
|
||||
@@ -320,21 +313,6 @@ get_host() {
|
||||
*BSD*)
|
||||
host=$(sysctl -n hw.vendor hw.product)
|
||||
;;
|
||||
|
||||
CYGWIN*|MSYS*|MINGW*)
|
||||
# Grab everything after the first instance of '=' in each
|
||||
# line of the command output of 'wmic'. Append the output
|
||||
# of each line to the '$host' variable.
|
||||
#
|
||||
# The format of 'wmic' is as follows:
|
||||
# Manufacturer=VMware, Inc.
|
||||
# Model=VMware Virtual Platform
|
||||
while IFS='=' read -r _ val; do
|
||||
host="${host}${val:+ $val}"
|
||||
done <<-EOF
|
||||
$(wmic computersystem get manufacturer,model /value)
|
||||
EOF
|
||||
;;
|
||||
esac
|
||||
|
||||
# Turn the host string into an argument list so we can iterate
|
||||
@@ -367,7 +345,7 @@ get_host() {
|
||||
case $word in
|
||||
To | [Bb]e | [Ff]illed | by | O.E.M. | OEM |\
|
||||
Not | Applicable | Specified | System | Product | Name |\
|
||||
Version | Undefined | Default | string | INVALID | <20> )
|
||||
Version | Undefined | Default | string | INVALID | <20> | os )
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
@@ -384,7 +362,7 @@ get_uptime() {
|
||||
# converting that data into days, hours and minutes using simple
|
||||
# math.
|
||||
case $os in
|
||||
Linux*|Minix*|CYGWIN*|MSYS*|MINGW*)
|
||||
Linux*|Minix*)
|
||||
IFS=. read -r s _ < /proc/uptime
|
||||
;;
|
||||
|
||||
@@ -460,6 +438,7 @@ get_pkgs() {
|
||||
Linux*)
|
||||
# Commands which print packages one per line.
|
||||
has bonsai && bonsai list
|
||||
has crux && pkginfo -i
|
||||
has pacman-key && pacman -Qq
|
||||
has dpkg && dpkg-query -f '.\n' -W
|
||||
has rpm && rpm -qa
|
||||
@@ -483,10 +462,24 @@ get_pkgs() {
|
||||
Darwin*)
|
||||
# Commands which print packages one per line.
|
||||
has pkgin && pkgin list
|
||||
has port && port installed
|
||||
|
||||
# Directories containing packages.
|
||||
has brew && printf '%s\n' /usr/local/Cellar/*
|
||||
|
||||
# 'port' prints a single line of output to 'stdout'
|
||||
# when no packages are installed and exits with
|
||||
# success causing a false-positive of 1 package
|
||||
# installed.
|
||||
#
|
||||
# 'port' should really exit with a non-zero code
|
||||
# in this case to allow scripts to cleanly handle
|
||||
# this behavior.
|
||||
has port && {
|
||||
pkg_list=$(port installed)
|
||||
|
||||
[ "$pkg_list" = "No ports are installed." ] ||
|
||||
printf '%s\n' "$pkg_list"
|
||||
}
|
||||
;;
|
||||
|
||||
FreeBSD*|DragonFly*)
|
||||
@@ -513,18 +506,10 @@ get_pkgs() {
|
||||
has pkginfo && pkginfo -i
|
||||
has pkg && pkg list
|
||||
;;
|
||||
|
||||
CYGWIN*)
|
||||
cygcheck -cd
|
||||
;;
|
||||
|
||||
MSYS*)
|
||||
pacman -Qq
|
||||
;;
|
||||
esac | wc -l
|
||||
`
|
||||
|
||||
log pkgs "${packages:-?}" >&6
|
||||
[ "$packages" -gt 1 ] && log pkgs "$packages" >&6
|
||||
}
|
||||
|
||||
get_memory() {
|
||||
@@ -532,7 +517,7 @@ get_memory() {
|
||||
# Used memory is calculated using the following "formula":
|
||||
# MemUsed = MemTotal + Shmem - MemFree - Buffers - Cached - SReclaimable
|
||||
# Source: https://github.com/KittyKatt/screenFetch/issues/386
|
||||
Linux*|CYGWIN*|MSYS*|MINGW*)
|
||||
Linux*)
|
||||
# Parse the '/proc/meminfo' file splitting on ':' and 'k'.
|
||||
# The format of the file is 'key: 000kB' and an additional
|
||||
# split is used on 'k' to filter out 'kB'.
|
||||
@@ -567,7 +552,7 @@ get_memory() {
|
||||
# split is used on '.' to filter it out.
|
||||
while IFS=:. read -r key val; do
|
||||
case $key in
|
||||
*wired*|*active*|*occupied*)
|
||||
*' wired'*|*' active'*|*' occupied'*)
|
||||
mem_used=$((mem_used + ${val:-0}))
|
||||
;;
|
||||
esac
|
||||
@@ -709,6 +694,67 @@ get_memory() {
|
||||
log memory "${mem_used:-?}M / ${mem_full:-?}M" >&6
|
||||
}
|
||||
|
||||
get_disk() {
|
||||
# Store the version of the 'df' command as the available
|
||||
# flags, options and implementation differs between operating
|
||||
# systems and we need to handle these edge-cases.
|
||||
df_version=$(df --version 2>&1)
|
||||
|
||||
case $df_version in
|
||||
# The 'df' command is from AIX.
|
||||
*IMitv*)
|
||||
set -- -P -g
|
||||
;;
|
||||
|
||||
# The 'df' command is from IRIX.
|
||||
*befhikm*)
|
||||
set -- -P -k
|
||||
;;
|
||||
|
||||
# The 'df' command is from OpenBSD.
|
||||
*hiklnP*)
|
||||
set -- -h
|
||||
;;
|
||||
|
||||
# The 'df' command is from Haiku and is wildly
|
||||
# different and provides no workable output,
|
||||
# end here.
|
||||
*Tracker*) # Haiku
|
||||
return
|
||||
;;
|
||||
|
||||
# From testing it is saffe to assume that
|
||||
# any other 'df' version provides these flags.
|
||||
*)
|
||||
set -- -P -h
|
||||
;;
|
||||
esac
|
||||
|
||||
# Read the output of 'df' line by line. The first line
|
||||
# contains header information for the "table" so it is
|
||||
# skipped.
|
||||
#
|
||||
# The next lines are then split to grab the relevant
|
||||
# information and thankfully the output remains the
|
||||
# same between all but one 'df' implementation.
|
||||
#
|
||||
# TODO: Configure disks to send to 'df'. Do we need to
|
||||
# do this? I'd love to _not_ do it.
|
||||
df "$@" / | while read -r name full used _ perc _; do
|
||||
[ "$header" ] || { header=1; continue; }
|
||||
|
||||
case $df_version in
|
||||
# The 'df' command is from IRIX.
|
||||
*befhikm*)
|
||||
used=$((used/1024/1024))G
|
||||
full=$((full/1024/1024))G
|
||||
;;
|
||||
esac
|
||||
|
||||
log disk "$name [$used / $full ($perc)]" >&6
|
||||
done
|
||||
}
|
||||
|
||||
get_wm() {
|
||||
case $os in
|
||||
# Don't display window manager on macOS.
|
||||
@@ -787,8 +833,17 @@ get_wm() {
|
||||
# To extract the name, everything before '_NET_WM_NAME = \"'
|
||||
# is removed and everything after the next '"' is removed.
|
||||
wm=$(xprop -id "$id" -notype -len 25 -f _NET_WM_NAME 8t)
|
||||
wm=${wm##*_NET_WM_NAME = \"}
|
||||
wm=${wm%%\"*}
|
||||
|
||||
# Handle cases of a window manager _not_ populating the
|
||||
# '_NET_WM_NAME' atom. Display nothing in this case.
|
||||
case $wm in
|
||||
*'_NET_WM_NAME = '*)
|
||||
wm=${wm##*_NET_WM_NAME = \"}
|
||||
wm=${wm%%\"*}
|
||||
;;
|
||||
|
||||
*) wm= ;;
|
||||
esac
|
||||
}
|
||||
;;
|
||||
esac
|
||||
@@ -894,13 +949,13 @@ get_ascii() {
|
||||
|
||||
[Aa]rch*)
|
||||
read_ascii 4 <<-EOF
|
||||
${c6} /\\
|
||||
/^^\\
|
||||
/\\ \\
|
||||
/${c7} __ \\
|
||||
/ ( ) \\
|
||||
/ __| |__\\\\
|
||||
/// \\\\\\
|
||||
${c6} /\\
|
||||
/ \\
|
||||
/\\ \\
|
||||
${c4} / \\
|
||||
/ ,, \\
|
||||
/ | | -\\
|
||||
/_-'' ''-_\\
|
||||
EOF
|
||||
;;
|
||||
|
||||
@@ -989,13 +1044,12 @@ get_ascii() {
|
||||
|
||||
[Ff]ree[Bb][Ss][Dd]*)
|
||||
read_ascii 1 <<-EOF
|
||||
${c1} /\\ _____ /\\
|
||||
\\_) (_/
|
||||
/ \\
|
||||
${c1}/\\,-'''''-,/\\
|
||||
\\_) (_/
|
||||
| |
|
||||
| |
|
||||
\ /
|
||||
--_____--
|
||||
; ;
|
||||
'-_____-'
|
||||
EOF
|
||||
;;
|
||||
|
||||
@@ -1011,7 +1065,7 @@ get_ascii() {
|
||||
EOF
|
||||
;;
|
||||
|
||||
[Gg]uix[Ss][Dd]*|guix*)
|
||||
[Gg]uix[Ss][Dd]*|[Gg]uix*)
|
||||
read_ascii 3 <<-EOF
|
||||
${c3}|.__ __.|
|
||||
|__ \\ / __|
|
||||
@@ -1048,7 +1102,7 @@ get_ascii() {
|
||||
EOF
|
||||
;;
|
||||
|
||||
[Ll]inux*[Ll]ite*)
|
||||
[Ll]inux*[Ll]ite*|[Ll]ite*)
|
||||
read_ascii 3 <<-EOF
|
||||
${c3} /\\
|
||||
/ \\
|
||||
@@ -1182,7 +1236,7 @@ get_ascii() {
|
||||
EOF
|
||||
;;
|
||||
|
||||
openSUSE*|open*SUSE*|SUSE*|suse*)
|
||||
[Oo]penSUSE*|[Oo]pen*SUSE*|SUSE*|suse*)
|
||||
read_ascii 2 <<-EOF
|
||||
${c2} _______
|
||||
__| __ \\
|
||||
@@ -1241,7 +1295,7 @@ get_ascii() {
|
||||
EOF
|
||||
;;
|
||||
|
||||
[Ss]un[Oo][Ss])
|
||||
[Ss]un[Oo][Ss]|[Ss]olaris*)
|
||||
read_ascii 3 <<-EOF
|
||||
${c3} . .; .
|
||||
. :; :: ;: .
|
||||
@@ -1309,8 +1363,12 @@ get_ascii() {
|
||||
# output without the use of a pipe ('|').
|
||||
# This ensures that any variables defined in the while loop
|
||||
# are still accessible in the script.
|
||||
#
|
||||
# The 'awk' command below used to be a simple 'sed', however
|
||||
# some versions of Android shipped with a totally broken 'sed'
|
||||
# command from 'toybox' and so we're forced to avoid 'sed'.
|
||||
done <<-EOF
|
||||
$(printf %s "$ascii" | sed 's/\[3.m//g')
|
||||
$(printf %s "$ascii" | awk '{gsub("\\[3.m","");print}')
|
||||
EOF
|
||||
|
||||
# Add a gap between the ascii art and the information.
|
||||
@@ -1333,6 +1391,11 @@ main() {
|
||||
# This gives full control over what it displayed on the screen.
|
||||
exec 6>&1 >/dev/null
|
||||
|
||||
# Ensure that the 'TMPDIR' is writable as heredocs use it and
|
||||
# fail without the write permission. This was found to be the
|
||||
# case on Android where the temporary directory requires root.
|
||||
[ -w "${TMPDIR:-/tmp}" ] || export TMPDIR=~
|
||||
|
||||
# Generic color list.
|
||||
# Disable warning about unused variables.
|
||||
# shellcheck disable=2034
|
||||
@@ -1408,7 +1471,7 @@ main() {
|
||||
# N lines.
|
||||
#
|
||||
# This was a ternary operation but they aren't supported in Minix's shell.
|
||||
[ "$info_height" -lt "$ascii_height" ] &&
|
||||
[ "${info_height:-0}" -lt "${ascii_height:-0}" ] &&
|
||||
cursor_pos=$((ascii_height - info_height))
|
||||
|
||||
# Print '$cursor_pos' amount of newlines to correctly position the
|
||||
|
||||
Reference in New Issue
Block a user