Tuesday, July 22, 2025

Bash + xdotool: Helping a Friend Escape the Daily Grind of Data Entry

 (Originally published in LinkedIn)

Recently I shared how I automated a repetitive RDP login sequence. Not long after I did that for me, a tech-savvy friend of mine (the kind of person who runs Linux by choice) reached out with a question:

“Hey, could you help me automate part of my daily job? I enter the same records every day into a remote system — it's mind-numbing.”

And so began the second phase of my GUI automation journey.


๐Ÿ“‹ The Scenario

Every day, my friend logs into a remote desktop application and enters a list of codes into a form. Each code corresponds to a client (or internal identifier) and must be entered with:

  • The date (defaulted to today)
  • A dropdown value for service type
  • A location code
  • A time range (morning or afternoon)
  • A group label (defaulted to "Group AM")

It's a classic case of repetitive data entry that’s just structured enough to automate — but still GUI-based, with no API or import functionality.


๐Ÿงช The Bash Script That Saves the Day

Here’s what I wrote to help:

# --- Configuration ---
SERVICE='h2017/n'
PLACE_OF_SERVICE='53'
MORNING_IDS=(1 2 3 4 5 6 7 8 9)
AFTERNOON_IDS=(10 11 12 13 14 15 16 17 18 19)

These are the values he uses every day. The script breaks the clients into Morning and Afternoon sessions.

To simulate user interaction, I used xdotool — a CLI tool that simulates keystrokes and mouse activity under X11.

type() { xdotool type "$1"; }
keystroke() { xdotool key "$1"; }
Tab() { keystroke 'Tab'; }

We define helper functions to keep the main script readable. Then we use a loop to type values into the form, tabbing between fields as needed.

process_entries() {
  local time="$1"
  local group_info="$2"
  shift 2
  local ids=("$@")

  for id in "${ids[@]}"; do
    Tab; type "$id"; Tab
    type "$SERVICE"; Tab
    type "$PLACE_OF_SERVICE"; Tab
    if [[ -n "$group_info" ]]; then
      type "$group_info"; Tab
    else
      Tab
    fi
    type "$time"; Tab; Tab
  done
}

And finally, the execution block that connects to the open RDP window and runs the whole show:

WINDOW_ID=$(xdotool search --onlyvisible --name FreeRDP | head -1)

if [[ -z "$WINDOW_ID" ]]; then
  echo "Error: FreeRDP window not found."
  exit 1
fi

xdotool windowactivate "$WINDOW_ID"
sleep 0.5

process_entries "0800 AM" "" "${MORNING_IDS[@]}"
process_entries "1230 PM" "Group PM" "${AFTERNOON_IDS[@]}"

The script automatically enters every morning record, followed by the afternoon ones — complete with optional group labels.


๐Ÿง  Lessons & Takeaways

This kind of automation is a great example of tech empowerment. My friend didn’t need a massive IT team or custom enterprise software — just a small, scriptable solution to take back a chunk of his day.

This approach is helpful when:

✅ You're stuck with a GUI-only workflow ✅ There's no API or backend access ✅ The process is highly repeatable and structured ✅ You trust the environment (i.e., the form layout doesn’t change)


⚠️ The Usual Caveats

  • GUI automation is fragile. A changed window name, an extra field, or a different layout can break things.
  • It’s best for stable, low-variance tasks.
  • Avoid storing sensitive data in plain scripts. Use environment variables or credential managers when possible.
  • Test thoroughly, and always keep manual backup options.


Let’s just say this script saves someone enough time each morning to enjoy an extra cup of coffee… without having to worry about any cover sheets.


๐Ÿ’ฌ Ever helped someone automate a boring daily task? Got your own war stories from the frontlines of manual data entry? Share them below — I’d love to hear how others tackle these real-world challenges.


No comments:

Post a Comment

Your Friendly Guide to Mastering the Linux Kernel with kernel-update

If you have ever explored the inner workings of Linux, you probably know that the kernel is the heart of your operating system. While most u...