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












0















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














bumped to the homepage by Community 11 hours ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.











  • 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


















0















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














bumped to the homepage by Community 11 hours ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.











  • 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
















0












0








0








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?







bash command-line printf text-user-interface






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 29 '17 at 11:43









unfaunfa

620514




620514





bumped to the homepage by Community 11 hours ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.







bumped to the homepage by Community 11 hours ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.










  • 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


















0














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































    0














    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',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    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















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    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




























      0














      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


























        0












        0








        0







        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 ParkerSilas Parker

        1635




        1635

























            0














            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
















            0














            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














            0












            0








            0







            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 TianX Tian

            7,73712136




            7,73712136








            • 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




















































            Thanks for contributing an answer to Unix & Linux Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            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















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Loup dans la culture

            How to solve the problem of ntp “Unable to contact time server” from KDE?

            Connection limited (no internet access)