2

There are many questions for this actually, but none of them seem to work for my specific needs.

I am using tmux and therefore my bash window is pretty small ($COLUMNS = 45). This means that pretty much any output is going to get wrapped at its maximum width, which can look pretty gross because long words are getting wrapped in the middle.

While many solutions (e.g. fold -w 30 -s $FILE) works fine with files, I can't seem to pipe output from running a program like python or nodejs. For readability's sake, I'd like to have their outputs wrapped at whitespace.

So for example, when I intentionally generate an error with nodejs asdgasgsdg by passing a non-existent file, I want the output to be:

Error: Cannot find module '/home/User/
Documents/cwd/asdgasdg'
    at Function.Module._resolveFilename (
module.js:326:15)
    at Function.Module._load (module.js:277:
25)
    at Function.Module.runMain (module.js:442
:10)
    at startup (node.js:136:18)
    at node.js:966:3

Instead of:

Error: Cannot find module '/home/User/Docume
nts/cwd/asdgasdg'
    at Function.Module._resolveFilename (modu
le.js:326:15)
...

I'd like a simple command that can force this kind of wrapping. I was thinking about something like nodejs non-existent-file.js | fold -w 45, which doesn't work.

I've also tried piping the output to a file then opening the file with fold, but I couldn't get nodejs to pipe its error message to output.txt. I don't want to manually force the script to log to a file but instead force the terminal to do the job. (i.e. I want a working equivalent of nodejs non-existent-file.js > output.txt; fold -w 45 -s output.txt. When I tried it, output.txt was empty.)

Is this possible?

2

Piping through fold does work with any program that doesn't require its output to be a terminal. And if the program requires its output to be a terminal, it's likely because it does its own formatting.

nodejs non-existent-file.js | fold -w 45 “doesn't work” because you aren't piping all the output into fold, only the standard output (i.e. application data). You need to join standard output with standard error into the pipe:

nodejs non-existent-file.js 2>&1 | fold -w 45

But there's an additional wrinkle. Data that is written to a pipe is normally bufferred whereas data is not buffered by default when writing to a terminal. Since the pipe is outputting to a terminal, you should disable buffering. With GNU utilities, you can use stdbuf.

Also, piping destroys the information of the command's return status. In bash, you can use PIPESTATUS to recover the status of the command; zsh has pipestatus to the same effect. Alternatively, in ksh93, bash or zsh, you can use a process substitution; however bash doesn't wait for the command in the process substitution to finish, which is also a problem.

Furthermore you should only do this wrapping if the output is a terminal. Wrapping logs in files would be very annoying since it destroys a lot of information (you can't rely on line breaks anymore).

#!/bin/bash
run_with_word_wrap () {
  if [ -t 1 ]; then
    stdbuf -oL -eL "$@" 2>&1 | fold -w "$COLUMNS"
    return ${PIPESTATUS[0]}
  else
    "$@"
  fi
}

run_with_word_wrap nodejs non-existent-file.js

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.