DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Git Bash (Or Git in Bash)?
  • Demystifying Event Storming: Process Modeling Level Event Storming (Part 2)
  • SonarQube Analysis With Ginkgo on Mac
  • Create a Kubernetes Cluster With Centos

Trending

  • Beyond ChatGPT, AI Reasoning 2.0: Engineering AI Models With Human-Like Reasoning
  • Measuring the Impact of AI on Software Engineering Productivity
  • Start Coding With Google Cloud Workstations
  • Artificial Intelligence, Real Consequences: Balancing Good vs Evil AI [Infographic]
  1. DZone
  2. Coding
  3. Languages
  4. Emulating the History Command Within a Bash Script

Emulating the History Command Within a Bash Script

This article is about seeking a script that offers a consistent interactive environment, enabling the user to navigate through previous inputs on the same input line.

By 
Constantin Kwiatkowski user avatar
Constantin Kwiatkowski
·
Nov. 26, 23 · Tutorial
Likes (1)
Comment
Save
Tweet
Share
2.3K Views

Join the DZone community and get the full member experience.

Join For Free

In the world of Unix-like operating systems, the command line is a powerful and efficient way to interact with your computer. Over time, as you work with your system, you might wonder: "How can I use a kind of history command to recall past commands within the interactivity of a bash script?" 

I am seeking a script that offers a consistent interactive environment, enabling me as a user to navigate through and execute previous commands seamlessly using arrow keys. The desired functionality involves the ability to scroll through a history of commands on the same input line, similar to the experience in the Bash shell.

The addition of this new feature provides developers with the flexibility to establish a more user-friendly environment within a Bash script, enhancing overall productivity for users engaging with the script. Additional reasons for incorporating this feature could include:

  1. Limited Execution Scope:

    • Explicitly define the scope of commands that your script can execute.
    • Consider using functions within your script to encapsulate specific tasks.
  2. User Input Validation:

    • Validate and sanitize user inputs to reduce the risk of unintended command execution.
    • Avoid blindly executing user-supplied data without proper validation.
  3. Environment Configuration:

    • Configure the script environment to mimic a safe and controlled environment.
    • Set specific environment variables or shell options to match your requirements.
  4. Command Whitelisting:

    • Explicitly whitelist or allow only a specific set of commands within your script.
    • Restrict the script's execution environment to a subset of safe commands.
  5. Logging and Auditing:

    • Implement logging to record the actions performed by the script.
    • Include detailed information in logs to facilitate auditing and debugging.
  6. Documentation:

    • Clearly document the purpose and usage of your script.
    • Provide information on any limitations or considerations regarding command execution.

The Read Command

Let's start with a simple readline. The following script simulate the key aspects of the history feature of the bash shell using the read command:

Shell
 
#!/bin/bash

# File to store simulated command history
history_file=".command_history"

# Function to add a command to history
add_to_history() {
    echo "$1" >> "$history_file"
}

# Function to view command history
view_history() {
    if [ -e "$history_file" ]; then
        echo "Command History:"
        cat "$history_file"
    else
        echo "No command history available."
    fi
}

# Function to clear command history
clear_history() {
    > "$history_file"
    echo "Command history cleared."
}

# Main script
while true; do
    echo "1. Add to history"
    echo "2. View history"
    echo "3. Clear history"
    echo "4. Quit"

    read -p "Choose an option (1-4): " choice

    case $choice in
        1)
            read -p "Enter command to add to history: " new_command
            add_to_history "$new_command"
            echo "Command added to history."
            ;;
        2)
            view_history
            ;;
        3)
            clear_history
            ;;
        4)
            echo "Exiting script."
            exit 0
            ;;
        *)
            echo "Invalid choice. Please enter a number between 1 and 4."
            ;;
    esac

    echo
done

Save this script to a file, make it executable (chmod +x script_name.sh), and then run it (./script_name.sh). The script will prompt you to add commands to history, view the history, clear the history, or exit the script. 

Comparing the script to the history feature of the Bash shell, the script above is very simple and inconvenient.  Let us create another script that is more convenient by using arrow keys. The script is designed to capture user keyboard input and provide interactive feedback based on the input. It handles special keys like arrow keys and displays their corresponding descriptions. Additionally, it simulates the history of commands, echoing user inputs as they are typed.

Shell
 
#!/bin/bash
function read_key()
{
    if read -rsn1 input
    then
        if [ "$input" = $'\x1B' ] # ESC ASCII code (https://dirask.com/posts/ASCII-Table-pJ3Y0j)
        then
            read -rsn1 -t 0.1 input
            if [ "$input" = "[" ]
            then
                read -rsn1 -t 0.1 input
                case "$input" in
                    A) echo '[Arrow Up]'   ;;
                    B) echo '[Arrow Down]' ;;
                    C) echo '[Arrow Right]';;
                    D) echo '[Arrow Left]' ;;
                esac
            fi
            read -rsn5 -t 0.1   # flushing stdin
        else
            echo "$input"
        fi
        return 0
    fi
    return 1
}

# Usage example:

while true
do
    input="$(read_key)"

    if [ "$?" -eq 0 ]
    then
        case "$input" in
            q) # q letter
                break
                ;;
            *) # arrows + other letters
                echo "$input"
                ;;
        esac
    fi
done

After some tests of different command options of the read command, it seems like the read command in bash is limited when it comes to emulating the full functionality of the history command with arrow key navigation.  

The Select Command

Next, let us try the bash built-in command select along with a custom history mechanism:

Shell
 
#!/bin/bash

# Custom command history
command_history=()

# Function to add a command to history
add_to_history() {
    command_history+=("$1")
}

# Function to display and execute commands interactively
interactive_menu() {
    PS3="Select a command (use arrow keys): "
    select command in "${command_history[@]}" "Exit"; do
        case $command in
            "Exit")
                break
                ;;
            *)
                echo "Executing: $command"
                eval "$command"
                ;;
        esac
    done
}

# Main script
while true; do
    read -e -p "Enter a command: " input_command

    # Add the command to history
    add_to_history "$input_command"

    # Execute the command
    eval "$input_command"

    # Display interactive menu
    interactive_menu
done

This script uses the select command to display a menu of previous commands, allowing the user to choose one for execution. The read -e option enables line editing, providing arrow key navigation. 

Like the read command, I did some manual tests with various scripts. The bottom line is the select command — as the read command — is limited when it comes to emulating the full functionality of the history command with arrow key navigation. 

Conclusion

I am looking for a constant interactivity within a script, allowing me as a user to navigate and execute previous commands by using arrow keys on the same input line. A kind of alteration of the read command, a read command with record functionality. 

The examples above show the tools and options in Bash are limited in order to emulate the history feature of the Bash shell. As result of my experiments, I developed a Bash script that works with some modifications and compromises:

Shell
 
#!/bin/bash

# Array to store command history
command_history=()
current_index=-1

# Function to execute a command
execute_command() {
    command="$1"
    echo "Executing: $command"
    # Add your command execution logic here
}

# Function to display the command history
display_history() {
    for ((i=0; i<${#command_history[@]}; i++)); do
        echo "$i: ${command_history[$i]}"
    done
}

# Function to handle arrow key events
handle_arrow_key() {
    case $1 in
        "A") # Up arrow key
            if [ $current_index -gt 0 ]; then
                ((current_index--))
            fi
            ;;

        "B") # Down arrow key
            if [ $current_index -lt $((${#command_history[@]} - 1)) ]; then
                ((current_index++))
            fi
            ;;

        *) # Other keys
            ;;
    esac
}

# Trap and handle arrow key presses
trap 'read -sn 1 arrow_key; handle_arrow_key "$arrow_key"' KEYBD

# Infinite loop for constant interactivity
while true; do
    read -e -p "> " user_input

    # Add the command to history
    command_history+=("$user_input")
    current_index=$((${#command_history[@]} - 1))

    # Execute the command
    execute_command "$user_input"

    # Display command history
    display_history
done

In essence, we are in need of a novel Bash tool that amalgamates the advantages offered by the read command and the history command. This tool aims to provide an enhanced, user-friendly experience compared to the basic read command. To initiate the development process, it is prudent to delve into the C code of the Bash shell. This exploration will offer valuable insights into the intricate workings of the history feature within the shell, serving as a solid foundation for the subsequent stages of development.

Bash (Unix shell) Command (computing) shell systems

Opinions expressed by DZone contributors are their own.

Related

  • Git Bash (Or Git in Bash)?
  • Demystifying Event Storming: Process Modeling Level Event Storming (Part 2)
  • SonarQube Analysis With Ginkgo on Mac
  • Create a Kubernetes Cluster With Centos

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!