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:
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() {