3

On a cluster where I am part of the management team, I often have to go through the multipage standard output of various commands such as sudo find / to look for any troubles such as broken links or to check the directory trees. At other times, I need to review long text files with lists of items on them to see if there are any unusual names.

Normally, piping the output through less, I can scroll pagewise but I figure it would be sufficient if the standard output scrolled a little slowly just like the credit roll at the end of a movie.

Is there a way to accomplish this in bash or any other terminal environment?

  • 7
    IMO less is far preferable to the hacky solutions provided by the answers, It's easier to type, should be available on every distribution, and you'll need a pager anyway whenever you suddendly decide that you want to scroll or search. – Martin von Wittich Jun 16 '16 at 16:55
  • When I need more than one look at the results, sudo find / > output.txt saves the output to a file, which can then be read in any text editor. – SauceCode Jun 17 '16 at 0:23
8

Answer from thrig's comment on OP. Works very well. Change the decimal after sleep to modify the time between lines.

sudo find / | awk '{system("sleep .5");print}'

Quit with ctrl+z and then kill the job (when using bash); ctrl+c only exits that line.

Edit:

Did some research based on a comment below. The suggestion awk '{system(sleep.5)||exit;print}' wasn't working on my system, but the following does seem to allow a ctrl+c exit.

awk '{if (system("sleep .5 && exit 2") != 2) exit; print}'

Putting it in a script or giving it an alias will save you from carpal tunnel.

  • This seems to be doing what I want. exiting is a bit tedious but I can live with that. – mkc Jun 16 '16 at 18:23
  • Something like awk '{system("sleep .5")||exit; print} would work, right? Or you could use perl which doesn't need to use an external command to sleep. – Peter Cordes Jun 16 '16 at 20:49
  • This is clever! – cat Jun 16 '16 at 21:41
8

pv, the pipe viewer, will let you print one line every second, use it like:

cat foo | pv --quiet --line-mode --rate-limit 1 

(or, shorter, pv -qlL1). In --line-mode, the --rate-limit (-L) flag defines the number of lines per second that will be printed; the higher the number, the faster the output.

It should be available in your distro's repositories (e.g. aptitude install pv to get it).

  • I didn't find a way to let the first several lines come through fast, and only rate limit after that. Of course, I couldn't imagine ever using this instead of less, and I think the OP is insane for wanting anything like this in the first place. – Peter Cordes Jun 16 '16 at 20:46
3

If its just the output of find you need to rate-limit in this manner, then you can just use find's -exec parameter to perform the sleep for each line:

sudo find / -exec sleep 0.2 \; -print
2

As promised in a previous answer, a simple C program. Why not? Boring day.

slower.c

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int main(int argc, char** argv) {
    int delay;
    char* rem;
    if (argc > 1) {
        delay = strtol(argv[1], &rem, 10);
    } else {
        delay = 500;
    }

    char* line;
    size_t bufsize = 0;

    struct timespec ts;
    ts.tv_sec = delay / 1000;
    ts.tv_nsec = (delay % 1000) * 1000000;

    while (getline(&line, &bufsize, stdin) != -1) {
        printf("%s", line);
        nanosleep(&ts, NULL);
    }
    free(line);
}

Compile with a nice gcc slower.c -o slower. If used with no arguments, the milliseconds per line defaults to 500.

Usage: sudo find / | ./slower [MILLISECONDS PER LINE]

Edit: Fixed up some of the code thanks to input in the comments. Apparently, getline doesn't even need your filthy malloc, or any default values. Let getline allocate the crap out of itself.

Edit 2: Removed the improper while (!feof(stdin)) usage and added back in the bufsize initialization for compatibility.

  • 2
    Also, not that this is Code Review but I implore you to A) not cast the result of malloc and B) not use atoi in place of better alternatives which should always be used instead of atoi – cat Jun 16 '16 at 21:28
  • 1
    32 seems awfully short to hardcode the max line length. Also, if you're hardcoding, then why not just statically allocate the line buffer as a char array instead of messing with malloc(). – Digital Trauma Jun 16 '16 at 21:32
  • 1
    I always appreciate a review of my code; I'm merely a student, and know next to nothing about best practices. I'll fix those shortly. – Landon Bland Jun 16 '16 at 21:33
  • 1
    There's no reason to malloc anyways, a char* line[32]; getline(...); will work fine. – cat Jun 16 '16 at 21:34
  • 1
    Reads man getline. Wow I didn't realize getline() does this: "If the buffer is not large enough to hold the line, getline() resizes it with realloc(3), updating *lineptr and *n as necessary." Carry on... – Digital Trauma Jun 16 '16 at 21:56

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.