logo

utils-std

Collection of commonly available Unix tools
commit: 163d7e89ac8742b919b859d7c7a6f3fd58ebfd60
parent 388be371d91938897924756e705fbaaf959b6361
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Mon,  1 Apr 2024 21:14:33 +0200

cmd/df: Only pad with spaces when stdout is a TTY

This way cut(1) becomes usable for extracting df(1) output.

Diffstat:

Mcmd/df.14+++-
Mcmd/df.c53++++++++++++++++++++++++++++-------------------------
Mtest-cmd/df14+++++++-------
3 files changed, 38 insertions(+), 33 deletions(-)

diff --git a/cmd/df.1 b/cmd/df.1 @@ -26,7 +26,9 @@ filters to the first filesystem containing each .Pp Unlike some implementations the table formatting isn't perfect, you might want to use .Xr column 1 -to get more readable outputs. +to get more readable output. +Also padding is disabled when output isn't a TTY so you can more easily use tools like +.Xr cut 1 . .Sh OPTIONS .Bl -tag -width Ds .It Fl a diff --git a/cmd/df.c b/cmd/df.c @@ -103,6 +103,11 @@ main(int argc, char *argv[]) int args_left = argc != 0 ? argc : 1; + bool tty_out = isatty(1); + int col_width = tty_out ? 10 : 0; + + if(!tty_out) fs_col_width = 0; + dev_t arg_devs[argc]; for(int i = 0; i < argc; i++) { @@ -120,14 +125,14 @@ main(int argc, char *argv[]) printf("%-*s ", fs_col_width, "Filesystem"); - if(opt_T) printf("%10s ", "Type"); + if(opt_T) printf("%*s ", col_width, "Type"); if(forced_bsize != 0) - printf("%3zd-blocks ", forced_bsize); + printf("%zd-blocks ", forced_bsize); else - printf("%10s ", "Total"); + printf("%*s ", col_width, "Total"); - printf("%10s %10s ", "Used", "Available"); + printf("%*s %*s ", col_width, "Used", col_width, "Available"); if(opt_P) printf("Capacity Mounted on\n"); @@ -251,9 +256,13 @@ main(int argc, char *argv[]) { printf("%-*s ", fs_col_width, mntent->mnt_fsname); - if(opt_T) printf("%10s ", mntent->mnt_type); + if(opt_T) printf("%*s ", col_width, mntent->mnt_type); - printf("%10s %10s %10s %4s %s\n", "-", "-", "-", "-", mntent->mnt_dir); + printf("%*s ", col_width, "-"); // total + printf("%*s ", col_width, "-"); // used + printf("%*s ", col_width, "-"); // free + printf("%*s ", tty_out ? 3 : 0, "-"); // percent + printf("%s\n", mntent->mnt_dir); } continue; @@ -286,7 +295,7 @@ main(int argc, char *argv[]) printf("%-*s ", fs_col_width, mntent->mnt_fsname); - if(opt_T) printf("%10s ", mntent->mnt_type); + if(opt_T) printf("%*s ", col_width, mntent->mnt_type); if(opt_h && !opt_P) { @@ -294,28 +303,22 @@ main(int argc, char *argv[]) struct si_scale used_scl = dtosi(used, true); struct si_scale free_scl = dtosi(free, true); - // clang-format off - printf("%7.2f%-3s %7.2f%-3s %7.2f%-3s %3zd%% %s\n", - total_scl.number, total_scl.prefix, - used_scl.number, used_scl.prefix, - free_scl.number, free_scl.prefix, - percent, - mntent->mnt_dir - ); - // clang-format on + int width_num = tty_out ? col_width - 3 : 0; + int width_pre = tty_out ? 3 : 0; + + printf("%*.2f%-*s ", width_num, total_scl.number, width_pre, total_scl.prefix); + printf("%*.2f%-*s ", width_num, used_scl.number, width_pre, used_scl.prefix); + printf("%*.2f%-*s ", width_num, free_scl.number, width_pre, free_scl.prefix); } else { - // clang-format off - printf("%10zd %10zd %10zd %3zd%% %s\n", - total, - used, - free, - percent, - mntent->mnt_dir - ); - // clang-format on + printf("%*zd ", col_width, total); + printf("%*zd ", col_width, used); + printf("%*zd ", col_width, free); } + + printf("%*zd%% ", tty_out ? 3 : 0, percent); + printf("%s\n", mntent->mnt_dir); } endmntent(mounted); diff --git a/test-cmd/df b/test-cmd/df @@ -7,19 +7,19 @@ posix_body() { # stderr ignored because not all filesystems allow statvfs from a normal user. # For example tracefs aka "/sys/kernel/debug/tracing" on Linux. - atf_check -e ignore -o 'match:Filesystem *512-blocks *Used *Available *Capacity *Mounted on' sh -c '../cmd/df -P | head -1' - atf_check -e ignore -o 'match:Filesystem *1024-blocks *Used *Available *Capacity *Mounted on' sh -c '../cmd/df -Pk | head -1' + atf_check -e ignore -o 'match:Filesystem 512-blocks Used Available Capacity Mounted on' sh -c '../cmd/df -P | head -1' + atf_check -e ignore -o 'match:Filesystem 1024-blocks Used Available Capacity Mounted on' sh -c '../cmd/df -Pk | head -1' - atf_check -e ignore -o 'match:^[^ ]* *[0-9]* *[0-9]* *[0-9]* *[0-9]*% [^ ]$' sh -c '../cmd/df -P | sed -n 2,\$p' - atf_check -e ignore -o 'match:^[^ ]* *[0-9]* *[0-9]* *[0-9]* *[0-9]*% [^ ]$' sh -c '../cmd/df -Pk | sed -n 2,\$p' + atf_check -e ignore -o 'match:^[^ ]* [0-9]* [0-9]* [0-9]* [0-9]*% [^ ]$' sh -c '../cmd/df -P | sed -n 2,\$p' + atf_check -e ignore -o 'match:^[^ ]* [0-9]* [0-9]* [0-9]* [0-9]*% [^ ]$' sh -c '../cmd/df -Pk | sed -n 2,\$p' - atf_check -e ignore -o 'match:^[^ ]* *[0-9]* *[0-9]* *[0-9]* *[0-9]*% [^ ]$' sh -c '../cmd/df -Pa | sed -n 2,\$p' - atf_check -e ignore -o 'match:^[^ ]* *[0-9]* *[0-9]* *[0-9]* *[0-9]*% [^ ]$' sh -c '../cmd/df -Pak | sed -n 2,\$p' + atf_check -e ignore -o 'match:^[^ ]* [0-9]* [0-9]* [0-9]* [0-9]*% [^ ]$' sh -c '../cmd/df -Pa | sed -n 2,\$p' + atf_check -e ignore -o 'match:^[^ ]* [0-9]* [0-9]* [0-9]* [0-9]*% [^ ]$' sh -c '../cmd/df -Pak | sed -n 2,\$p' } atf_test_case args args_body() { - atf_check -e ignore -o 'match:^[^ ]* *[0-9]* *[0-9]* *[0-9]* *[0-9]*% /$' sh -c '../cmd/df -P / | sed -n 2,\$p' + atf_check -e ignore -o 'match:^[^ ]* [0-9]* [0-9]* [0-9]* [0-9]*% /$' sh -c '../cmd/df -P / | sed -n 2,\$p' } atf_init_test_cases() {