Best way to create table-like CLI display in Bash?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
0
down vote

favorite












I'm working on a Bash script for massive USB flash memory testing (using f3 under the hood). I need to display a table-like interface with multiple columns and cells.



Currently I'm using printf with and it looks like this:



enter image description here



I have a separate function running for each drive that write out text to a log file. These log files are parsed to display the information to the user.



As you can see some rows have offsets that shouldn't be there but I can't get rid of them It doesn't seem to be caused by long strings being printed. I don't know what's this.



Another problems I have is the refresh time and the need to manually clear and redraw the whole screen at times, due to ocasional stderr messages appearing there from grep or cat when some files don't read properly.



I'm currently doing a partial rewrite of this script and I what I could od better in regard to printing out the data on the screen. I thought about looking into ncurses but that seems like a bit too complicated thing and would probably make things way to complex for me to maintain.



I wonder if there is a way for me to dump the echo or print commands to a text file and then execute that all at once to basically have a text "backbuffer" so my refresh can be more consistent and faster?



I would also want to be able to listen for user's keystrokes and react to that in the background but that's not a priority.



Maybe there's a better way to do this kind of thing in Bash, that I don't know of?







share|improve this question
















  • 1




    Have you tried ncurses?
    – NarÅ«nasK
    Nov 29 '17 at 12:06










  • I haven't tried it, but I wondered if maybe there's a simpler way that wouldn't require me to learn it.
    – unfa
    Nov 29 '17 at 12:21










  • Possibly there are some TABs or other characters that have a display width other than 1, or multi-byte characters in your data. See also Why is printf "shrinking" umlaut?
    – Stéphane Chazelas
    Nov 29 '17 at 14:08















up vote
0
down vote

favorite












I'm working on a Bash script for massive USB flash memory testing (using f3 under the hood). I need to display a table-like interface with multiple columns and cells.



Currently I'm using printf with and it looks like this:



enter image description here



I have a separate function running for each drive that write out text to a log file. These log files are parsed to display the information to the user.



As you can see some rows have offsets that shouldn't be there but I can't get rid of them It doesn't seem to be caused by long strings being printed. I don't know what's this.



Another problems I have is the refresh time and the need to manually clear and redraw the whole screen at times, due to ocasional stderr messages appearing there from grep or cat when some files don't read properly.



I'm currently doing a partial rewrite of this script and I what I could od better in regard to printing out the data on the screen. I thought about looking into ncurses but that seems like a bit too complicated thing and would probably make things way to complex for me to maintain.



I wonder if there is a way for me to dump the echo or print commands to a text file and then execute that all at once to basically have a text "backbuffer" so my refresh can be more consistent and faster?



I would also want to be able to listen for user's keystrokes and react to that in the background but that's not a priority.



Maybe there's a better way to do this kind of thing in Bash, that I don't know of?







share|improve this question
















  • 1




    Have you tried ncurses?
    – NarÅ«nasK
    Nov 29 '17 at 12:06










  • I haven't tried it, but I wondered if maybe there's a simpler way that wouldn't require me to learn it.
    – unfa
    Nov 29 '17 at 12:21










  • Possibly there are some TABs or other characters that have a display width other than 1, or multi-byte characters in your data. See also Why is printf "shrinking" umlaut?
    – Stéphane Chazelas
    Nov 29 '17 at 14:08













up vote
0
down vote

favorite









up vote
0
down vote

favorite











I'm working on a Bash script for massive USB flash memory testing (using f3 under the hood). I need to display a table-like interface with multiple columns and cells.



Currently I'm using printf with and it looks like this:



enter image description here



I have a separate function running for each drive that write out text to a log file. These log files are parsed to display the information to the user.



As you can see some rows have offsets that shouldn't be there but I can't get rid of them It doesn't seem to be caused by long strings being printed. I don't know what's this.



Another problems I have is the refresh time and the need to manually clear and redraw the whole screen at times, due to ocasional stderr messages appearing there from grep or cat when some files don't read properly.



I'm currently doing a partial rewrite of this script and I what I could od better in regard to printing out the data on the screen. I thought about looking into ncurses but that seems like a bit too complicated thing and would probably make things way to complex for me to maintain.



I wonder if there is a way for me to dump the echo or print commands to a text file and then execute that all at once to basically have a text "backbuffer" so my refresh can be more consistent and faster?



I would also want to be able to listen for user's keystrokes and react to that in the background but that's not a priority.



Maybe there's a better way to do this kind of thing in Bash, that I don't know of?







share|improve this question












I'm working on a Bash script for massive USB flash memory testing (using f3 under the hood). I need to display a table-like interface with multiple columns and cells.



Currently I'm using printf with and it looks like this:



enter image description here



I have a separate function running for each drive that write out text to a log file. These log files are parsed to display the information to the user.



As you can see some rows have offsets that shouldn't be there but I can't get rid of them It doesn't seem to be caused by long strings being printed. I don't know what's this.



Another problems I have is the refresh time and the need to manually clear and redraw the whole screen at times, due to ocasional stderr messages appearing there from grep or cat when some files don't read properly.



I'm currently doing a partial rewrite of this script and I what I could od better in regard to printing out the data on the screen. I thought about looking into ncurses but that seems like a bit too complicated thing and would probably make things way to complex for me to maintain.



I wonder if there is a way for me to dump the echo or print commands to a text file and then execute that all at once to basically have a text "backbuffer" so my refresh can be more consistent and faster?



I would also want to be able to listen for user's keystrokes and react to that in the background but that's not a priority.



Maybe there's a better way to do this kind of thing in Bash, that I don't know of?









share|improve this question











share|improve this question




share|improve this question










asked Nov 29 '17 at 11:43









unfa

516212




516212







  • 1




    Have you tried ncurses?
    – NarÅ«nasK
    Nov 29 '17 at 12:06










  • I haven't tried it, but I wondered if maybe there's a simpler way that wouldn't require me to learn it.
    – unfa
    Nov 29 '17 at 12:21










  • Possibly there are some TABs or other characters that have a display width other than 1, or multi-byte characters in your data. See also Why is printf "shrinking" umlaut?
    – Stéphane Chazelas
    Nov 29 '17 at 14:08













  • 1




    Have you tried ncurses?
    – NarÅ«nasK
    Nov 29 '17 at 12:06










  • I haven't tried it, but I wondered if maybe there's a simpler way that wouldn't require me to learn it.
    – unfa
    Nov 29 '17 at 12:21










  • Possibly there are some TABs or other characters that have a display width other than 1, or multi-byte characters in your data. See also Why is printf "shrinking" umlaut?
    – Stéphane Chazelas
    Nov 29 '17 at 14:08








1




1




Have you tried ncurses?
– NarÅ«nasK
Nov 29 '17 at 12:06




Have you tried ncurses?
– NarÅ«nasK
Nov 29 '17 at 12:06












I haven't tried it, but I wondered if maybe there's a simpler way that wouldn't require me to learn it.
– unfa
Nov 29 '17 at 12:21




I haven't tried it, but I wondered if maybe there's a simpler way that wouldn't require me to learn it.
– unfa
Nov 29 '17 at 12:21












Possibly there are some TABs or other characters that have a display width other than 1, or multi-byte characters in your data. See also Why is printf "shrinking" umlaut?
– Stéphane Chazelas
Nov 29 '17 at 14:08





Possibly there are some TABs or other characters that have a display width other than 1, or multi-byte characters in your data. See also Why is printf "shrinking" umlaut?
– Stéphane Chazelas
Nov 29 '17 at 14:08











2 Answers
2






active

oldest

votes

















up vote
0
down vote













You could use tput to move the cursor around, for example tput cup 0 0; echo test will put write "test" to the top left of the screen.



Alternatively, if you wanted to use a buffered approach, you could dump lines to a file, clear the screen and cat the file:



# In program setup
TEMPFILE=$(mktemp) # Create temporary file
trap "rm -f $TEMPFILE" EXIT # Remove temporary on exit

# Main lopp
while true
do
echo "TEST" >$TEMPFILE # Clear file and set first line with >
date >>$TEMPFILE # Append lines to file with >>

clear # Clear the screen
cat $TEMPFILE # Dump the file
sleep 1 # Just for testing to avoid high CPU
done


Comment out the trap line if you want to leave the temporary file behind for debugging.






share|improve this answer



























    up vote
    0
    down vote













    I think you have nearly achieved what you set out to do, albeit with a few minor bugs and possibly some performance problems. Personally, I would first try to solve the bugs, then try to understand where the performance could be improved. However regarding your refresh rate, even programs like top or watch usually run with a refresh every 2 or 1 seconds and this is usually sufficient. You don't say, what rate you are trying to achieve.



    There is a similar Stackexchange question, which has two answers/suggestions,



    1. Use the program dialog which is something else to learn.

    2. Shows the creation of bash functions, to clear, reset, write text at a position on the screen, which is a similar set of functions that you would probably use in ncurses, but has the advantage of using echo (a bash built in function) so it doesn't bear the overhead of running /usr/bin/printf to format the output.

    Taking your problems in turn.



    1. errors being printed from background commands.
      Redirect, stderr either to /dev/null if you just want to discard it or to a file for later processing.


    2. Columns bug, show your code, input data nd required output, then we can make suggestions. This bug might be an affect of bug #1, so solve #1 first then address this if it still exists.


    3. Performance, (edit your question) and add your code so that we can see what you are doing and make suggestions.


    The other way is to use a different script interpreter, there are so many which to choose depends on which ones you are familiar with. (awk, python, perl, other shells, ...). However if you were not going to use ncurses, the principle would be similar to the bash function definitions shown in the 2nd answer above.






    share|improve this answer
















    • 1




      I would tend to agree that this is a bug issue. My biggest concern is that OP has ".... a separate function for each ....". I hope OP means ".... an instance of the same function for each......". Assuming the latter then the usb() function just needs to standardise what is written to the log file (fixed width/delimited etc) and most of the issues should be sorted. Personally I would also write the usb states to a 'model' and then draw the screen with a 'view' a la MVC. Easy maintenance.
      – bu5hman
      Nov 29 '17 at 14:29










    Your Answer







    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "106"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f407721%2fbest-way-to-create-table-like-cli-display-in-bash%23new-answer', 'question_page');

    );

    Post as a guest






























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    0
    down vote













    You could use tput to move the cursor around, for example tput cup 0 0; echo test will put write "test" to the top left of the screen.



    Alternatively, if you wanted to use a buffered approach, you could dump lines to a file, clear the screen and cat the file:



    # In program setup
    TEMPFILE=$(mktemp) # Create temporary file
    trap "rm -f $TEMPFILE" EXIT # Remove temporary on exit

    # Main lopp
    while true
    do
    echo "TEST" >$TEMPFILE # Clear file and set first line with >
    date >>$TEMPFILE # Append lines to file with >>

    clear # Clear the screen
    cat $TEMPFILE # Dump the file
    sleep 1 # Just for testing to avoid high CPU
    done


    Comment out the trap line if you want to leave the temporary file behind for debugging.






    share|improve this answer
























      up vote
      0
      down vote













      You could use tput to move the cursor around, for example tput cup 0 0; echo test will put write "test" to the top left of the screen.



      Alternatively, if you wanted to use a buffered approach, you could dump lines to a file, clear the screen and cat the file:



      # In program setup
      TEMPFILE=$(mktemp) # Create temporary file
      trap "rm -f $TEMPFILE" EXIT # Remove temporary on exit

      # Main lopp
      while true
      do
      echo "TEST" >$TEMPFILE # Clear file and set first line with >
      date >>$TEMPFILE # Append lines to file with >>

      clear # Clear the screen
      cat $TEMPFILE # Dump the file
      sleep 1 # Just for testing to avoid high CPU
      done


      Comment out the trap line if you want to leave the temporary file behind for debugging.






      share|improve this answer






















        up vote
        0
        down vote










        up vote
        0
        down vote









        You could use tput to move the cursor around, for example tput cup 0 0; echo test will put write "test" to the top left of the screen.



        Alternatively, if you wanted to use a buffered approach, you could dump lines to a file, clear the screen and cat the file:



        # In program setup
        TEMPFILE=$(mktemp) # Create temporary file
        trap "rm -f $TEMPFILE" EXIT # Remove temporary on exit

        # Main lopp
        while true
        do
        echo "TEST" >$TEMPFILE # Clear file and set first line with >
        date >>$TEMPFILE # Append lines to file with >>

        clear # Clear the screen
        cat $TEMPFILE # Dump the file
        sleep 1 # Just for testing to avoid high CPU
        done


        Comment out the trap line if you want to leave the temporary file behind for debugging.






        share|improve this answer












        You could use tput to move the cursor around, for example tput cup 0 0; echo test will put write "test" to the top left of the screen.



        Alternatively, if you wanted to use a buffered approach, you could dump lines to a file, clear the screen and cat the file:



        # In program setup
        TEMPFILE=$(mktemp) # Create temporary file
        trap "rm -f $TEMPFILE" EXIT # Remove temporary on exit

        # Main lopp
        while true
        do
        echo "TEST" >$TEMPFILE # Clear file and set first line with >
        date >>$TEMPFILE # Append lines to file with >>

        clear # Clear the screen
        cat $TEMPFILE # Dump the file
        sleep 1 # Just for testing to avoid high CPU
        done


        Comment out the trap line if you want to leave the temporary file behind for debugging.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 29 '17 at 13:43









        Silas Parker

        1714




        1714






















            up vote
            0
            down vote













            I think you have nearly achieved what you set out to do, albeit with a few minor bugs and possibly some performance problems. Personally, I would first try to solve the bugs, then try to understand where the performance could be improved. However regarding your refresh rate, even programs like top or watch usually run with a refresh every 2 or 1 seconds and this is usually sufficient. You don't say, what rate you are trying to achieve.



            There is a similar Stackexchange question, which has two answers/suggestions,



            1. Use the program dialog which is something else to learn.

            2. Shows the creation of bash functions, to clear, reset, write text at a position on the screen, which is a similar set of functions that you would probably use in ncurses, but has the advantage of using echo (a bash built in function) so it doesn't bear the overhead of running /usr/bin/printf to format the output.

            Taking your problems in turn.



            1. errors being printed from background commands.
              Redirect, stderr either to /dev/null if you just want to discard it or to a file for later processing.


            2. Columns bug, show your code, input data nd required output, then we can make suggestions. This bug might be an affect of bug #1, so solve #1 first then address this if it still exists.


            3. Performance, (edit your question) and add your code so that we can see what you are doing and make suggestions.


            The other way is to use a different script interpreter, there are so many which to choose depends on which ones you are familiar with. (awk, python, perl, other shells, ...). However if you were not going to use ncurses, the principle would be similar to the bash function definitions shown in the 2nd answer above.






            share|improve this answer
















            • 1




              I would tend to agree that this is a bug issue. My biggest concern is that OP has ".... a separate function for each ....". I hope OP means ".... an instance of the same function for each......". Assuming the latter then the usb() function just needs to standardise what is written to the log file (fixed width/delimited etc) and most of the issues should be sorted. Personally I would also write the usb states to a 'model' and then draw the screen with a 'view' a la MVC. Easy maintenance.
              – bu5hman
              Nov 29 '17 at 14:29














            up vote
            0
            down vote













            I think you have nearly achieved what you set out to do, albeit with a few minor bugs and possibly some performance problems. Personally, I would first try to solve the bugs, then try to understand where the performance could be improved. However regarding your refresh rate, even programs like top or watch usually run with a refresh every 2 or 1 seconds and this is usually sufficient. You don't say, what rate you are trying to achieve.



            There is a similar Stackexchange question, which has two answers/suggestions,



            1. Use the program dialog which is something else to learn.

            2. Shows the creation of bash functions, to clear, reset, write text at a position on the screen, which is a similar set of functions that you would probably use in ncurses, but has the advantage of using echo (a bash built in function) so it doesn't bear the overhead of running /usr/bin/printf to format the output.

            Taking your problems in turn.



            1. errors being printed from background commands.
              Redirect, stderr either to /dev/null if you just want to discard it or to a file for later processing.


            2. Columns bug, show your code, input data nd required output, then we can make suggestions. This bug might be an affect of bug #1, so solve #1 first then address this if it still exists.


            3. Performance, (edit your question) and add your code so that we can see what you are doing and make suggestions.


            The other way is to use a different script interpreter, there are so many which to choose depends on which ones you are familiar with. (awk, python, perl, other shells, ...). However if you were not going to use ncurses, the principle would be similar to the bash function definitions shown in the 2nd answer above.






            share|improve this answer
















            • 1




              I would tend to agree that this is a bug issue. My biggest concern is that OP has ".... a separate function for each ....". I hope OP means ".... an instance of the same function for each......". Assuming the latter then the usb() function just needs to standardise what is written to the log file (fixed width/delimited etc) and most of the issues should be sorted. Personally I would also write the usb states to a 'model' and then draw the screen with a 'view' a la MVC. Easy maintenance.
              – bu5hman
              Nov 29 '17 at 14:29












            up vote
            0
            down vote










            up vote
            0
            down vote









            I think you have nearly achieved what you set out to do, albeit with a few minor bugs and possibly some performance problems. Personally, I would first try to solve the bugs, then try to understand where the performance could be improved. However regarding your refresh rate, even programs like top or watch usually run with a refresh every 2 or 1 seconds and this is usually sufficient. You don't say, what rate you are trying to achieve.



            There is a similar Stackexchange question, which has two answers/suggestions,



            1. Use the program dialog which is something else to learn.

            2. Shows the creation of bash functions, to clear, reset, write text at a position on the screen, which is a similar set of functions that you would probably use in ncurses, but has the advantage of using echo (a bash built in function) so it doesn't bear the overhead of running /usr/bin/printf to format the output.

            Taking your problems in turn.



            1. errors being printed from background commands.
              Redirect, stderr either to /dev/null if you just want to discard it or to a file for later processing.


            2. Columns bug, show your code, input data nd required output, then we can make suggestions. This bug might be an affect of bug #1, so solve #1 first then address this if it still exists.


            3. Performance, (edit your question) and add your code so that we can see what you are doing and make suggestions.


            The other way is to use a different script interpreter, there are so many which to choose depends on which ones you are familiar with. (awk, python, perl, other shells, ...). However if you were not going to use ncurses, the principle would be similar to the bash function definitions shown in the 2nd answer above.






            share|improve this answer












            I think you have nearly achieved what you set out to do, albeit with a few minor bugs and possibly some performance problems. Personally, I would first try to solve the bugs, then try to understand where the performance could be improved. However regarding your refresh rate, even programs like top or watch usually run with a refresh every 2 or 1 seconds and this is usually sufficient. You don't say, what rate you are trying to achieve.



            There is a similar Stackexchange question, which has two answers/suggestions,



            1. Use the program dialog which is something else to learn.

            2. Shows the creation of bash functions, to clear, reset, write text at a position on the screen, which is a similar set of functions that you would probably use in ncurses, but has the advantage of using echo (a bash built in function) so it doesn't bear the overhead of running /usr/bin/printf to format the output.

            Taking your problems in turn.



            1. errors being printed from background commands.
              Redirect, stderr either to /dev/null if you just want to discard it or to a file for later processing.


            2. Columns bug, show your code, input data nd required output, then we can make suggestions. This bug might be an affect of bug #1, so solve #1 first then address this if it still exists.


            3. Performance, (edit your question) and add your code so that we can see what you are doing and make suggestions.


            The other way is to use a different script interpreter, there are so many which to choose depends on which ones you are familiar with. (awk, python, perl, other shells, ...). However if you were not going to use ncurses, the principle would be similar to the bash function definitions shown in the 2nd answer above.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 29 '17 at 13:50









            X Tian

            7,31111836




            7,31111836







            • 1




              I would tend to agree that this is a bug issue. My biggest concern is that OP has ".... a separate function for each ....". I hope OP means ".... an instance of the same function for each......". Assuming the latter then the usb() function just needs to standardise what is written to the log file (fixed width/delimited etc) and most of the issues should be sorted. Personally I would also write the usb states to a 'model' and then draw the screen with a 'view' a la MVC. Easy maintenance.
              – bu5hman
              Nov 29 '17 at 14:29












            • 1




              I would tend to agree that this is a bug issue. My biggest concern is that OP has ".... a separate function for each ....". I hope OP means ".... an instance of the same function for each......". Assuming the latter then the usb() function just needs to standardise what is written to the log file (fixed width/delimited etc) and most of the issues should be sorted. Personally I would also write the usb states to a 'model' and then draw the screen with a 'view' a la MVC. Easy maintenance.
              – bu5hman
              Nov 29 '17 at 14:29







            1




            1




            I would tend to agree that this is a bug issue. My biggest concern is that OP has ".... a separate function for each ....". I hope OP means ".... an instance of the same function for each......". Assuming the latter then the usb() function just needs to standardise what is written to the log file (fixed width/delimited etc) and most of the issues should be sorted. Personally I would also write the usb states to a 'model' and then draw the screen with a 'view' a la MVC. Easy maintenance.
            – bu5hman
            Nov 29 '17 at 14:29




            I would tend to agree that this is a bug issue. My biggest concern is that OP has ".... a separate function for each ....". I hope OP means ".... an instance of the same function for each......". Assuming the latter then the usb() function just needs to standardise what is written to the log file (fixed width/delimited etc) and most of the issues should be sorted. Personally I would also write the usb states to a 'model' and then draw the screen with a 'view' a la MVC. Easy maintenance.
            – bu5hman
            Nov 29 '17 at 14:29

















             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f407721%2fbest-way-to-create-table-like-cli-display-in-bash%23new-answer', 'question_page');

            );

            Post as a guest













































































            Popular posts from this blog

            How to check contact read email or not when send email to Individual?

            Bahrain

            Postfix configuration issue with fips on centos 7; mailgun relay