0

I have got a set of scripts that all source some common context:

DEFAULT_PAGINATION=''

ownContext=$HOME/.config/exploitation/context.sh
if [ -f "$ownContext" ]; then
  # shellcheck source=$HOME/.config/exploitation/context.sh
  . "$ownContext"
fi

That way anybody can override the default config: some locations, help flags and in this case, pagination.

To automatically redirect to less, for instance, I have tried that:

# DEFAULT_PAGINATION is the default pagination tool (a program)
# OUTPUT_PAGINATION_FILE acts as an include guard, or contains a filename

if [ -n "$DEFAULT_PAGINATION" ] && [ -z "$OUTPUT_PAGINATION_FILE" ]; then
  paginate() {
    $DEFAULT_PAGINATION "$OUTPUT_PAGINATION_FILE" # paginate tempfile
  }
  trap paginate exit
  OUTPUT_PAGINATION_FILE=$(mktemp)
  export OUTPUT_PAGINATION_FILE
  exec 1<&- # close stdout
  exec 1<>"$OUTPUT_PAGINATION_FILE" # redirect stdout to a temp file
fi

and export DEFAULT_PAGINATION=less in the other context file, but it doesn't work. Any idea ?

Plus, that solution does not allow export DEFAULT_PAGINATION="less +F" and on the fly redirection. Is there a solution to do that ?

P.S. the bash tag is intentionnal

2 Answers 2

1

I'm not sure if it can be done only by sourcing something. It can be done with a custom interpreter (wrapper).

Save this example piece of code as bash-pager:

#!/bin/sh

if [ -t 1 ] && [ -n "$PAGER" ]; then
    bash "$@" | sh -c "$PAGER"
else
    exec bash "$@"
fi

Make it executable (chmod +x bash-pager). Then change the shebang of these scripts you mentioned to

#!/full/path/to/bash-pager

or maybe (if bash-pager is reachable via $PATH) to:

#!/usr/bin/env bash-pager

In effect, if you have PAGER set and exported, the scripts will use it.


I used PAGER because it's kinda standard. You may want your bash-pager look more like this:

#!/bin/sh

ownContext="$HOME/.config/exploitation/context.sh"
if [ -f "$ownContext" ]; then
  . "$ownContext"
fi

DEFAULT_PAGINATION="${DEFAULT_PAGINATION:-$PAGER}"

if [ -t 1 ] && [ -n "$DEFAULT_PAGINATION" ]; then
    bash "$@" | sh -c "$DEFAULT_PAGINATION"
else
    exec bash "$@"
fi

Notes:

  • As you can see $DEFAULT_PAGINATION is used with sh -c, so you can pass a command with arguments (e.g. DEFAULT_PAGINATION='cat -n') or a pipeline.
  • [ -t 1 ] checks if stdout is a terminal. Thanks to this precaution you can still run one_of_your_scripts | whatever and DEFAULT_PAGINATION will not interfere.
  • PAGER can still be used. See this question.
  • I don't know what context.sh is supposed to do. Few concerns:

    • context.sh may do something you don't want in the context of interpreter, so sourcing it in bash-pager may not be desired.
    • context.sh may do something you explicitly want in your script(s), so you'd like to source it in every script anyway.
    • context.sh may require bash. Note bash-pager is designed to wrap over bash but its interpreter (shebang) is /bin/sh. Changing to bash is trivial though.
    • context.sh may use set to alter $@. If it does then "$@" later in bash-pager may not expand to what we need.

    This is for you to solve. Note the interpreter only needs DEFAULT_PAGINATION/PAGER. You can tell users to set and export one of these in their profile (if they want the functionality). Then bash-pager won't need to source anything.

1
  • That's brilliant. Context is some definitions i dont want to put in my coworker's .profile. Oct 23, 2019 at 19:31
0

Let's say you have script1.sh you want to paginate using less.

You can create a wrapper script that will paginate the script1.sh like this:

#!/usr/bin/env bash

/path/to/script1.sh | less

When you run the wrapper script it will run the script1.sh and paginate it using less.

Is there any reason why this doesn't work for you?

5
  • Yeah, there is ! Imagine I have a set of scripts ; all of which source some context.sh file. Can you imagine doing something in the context file so that every thing written after sourcing the context by the super-scripts is redirected toward some pagination ? Oct 22, 2019 at 22:04
  • Maybe exec 2>&1 | less +F would work ? gotta test that Oct 22, 2019 at 22:12
  • I don't think it's possible to redirect the output of the script from within the script. However, I don't get why you don't wrap each of the scripts individually and paginate using what I suggested above. If you don't like the part when you need to wrap the scripts one by one you can create a wrapper that will take care of the pagination for all of the scripts. I could create a small example for you but maybe it's going to be more useful if you include some sample code with your question.
    – curusarn
    Oct 22, 2019 at 23:24
  • I have put together a small example that shows how you can paginate a set of scripts without creating a separate wrapper for each of them: github.com/curusarn/superuser-question-paginate
    – curusarn
    Oct 22, 2019 at 23:52
  • If there is something specific about your scripts please post a sample code.
    – curusarn
    Oct 22, 2019 at 23:58

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .