3

I am looking for:

  1. a way to search inside odt files (i.e. search for contents, not name)
  2. that does not require any kind of indexing
  3. that is graphical and very user-friendly (for a relatively old person, who does not like computers much)

I know that it is possible to have 1) and 2):

for x in `find . -iname '*odt'`; do odt2txt $x | grep Query; done

works well enough, and it's pretty fast. But I wonder if there is already a good solution that does this with a GUI (or can be adapted to do this easily)

  • 1
    First your script have problems if there are spaces in the filename. To solve this look at this unix.stackexchange.com/questions/9496/… – TuKsn Jun 10 '14 at 17:26
  • 1
    How about a nautilus script with zenity input for the search term? – TuKsn Jun 10 '14 at 18:02
  • Yeah zenity can output the results as well. – hytromo Jun 10 '14 at 19:49
4

Solution using a yad script


Overview

Unfortunately there's no existing GUI option that would be able to search through LibreOffice documents without creating an index first (e.g. Recoll, Tracker). The closest one I found was gnome-search-tool but it only supports plain text files.

Because I was looking for the same type of functionality a few months ago I decided to sit down and see what I could come up with myself. So, without further ado, here's the script I wrote:

ODT finder

#!/bin/bash

# NAME:           ODT finder
# AUTHOR:         (c) 2014 Glutanimate (https://github.com/Glutanimate)
# LICENSE:        GNU GPLv3 (http://www.gnu.de/documents/gpl-3.0.en.html)
# DEPENDENCIES    yad libreoffice unoconv


# Dialogs

Title="ODT finder"
TxtEntry="Please enter the <b>directory</b> you would like to search through \
and the <b>search term.</b>"
ErrNoArgs="ERROR: Please make sure to supply both a search path and search term"
ErrNoReslt="No results found."

# Variables

declare -A Results

# Functions

dialog_options(){
    SearchOptions="$(yad --form --title="$Title" --text="$TxtEntry" \
    --width=400 --height=200 --center \
    --field="Directory":DIR \
    --field="Search term" )"

    RET="$?"

    if [[ "$RET" != "0" ]]; then
      echo "Aborting"
      exit 1
    fi   

    SearchPath="$(echo "$SearchOptions" | cut -d '|' -f1)"
    SearchTerm="$(echo "$SearchOptions" | cut -d '|' -f2)"

    echo "Path: $SearchPath"
    echo "Query: $SearchTerm"

    if [[ -z "$SearchPath" || -z "$SearchTerm" ]]; then
      dialog_error "$ErrNoArgs"
      dialog_options
    fi
}


odt_search(){
    while IFS= read -r -d '' File; do
        Match="$(unoconv --format txt --stdout "$File" 2> /dev/null  | grep -m "1" -i "$SearchTerm")"
        if [[ -n "$Match" ]]
          then
              echo "Match found for $File:"
              echo "$Match"
              Results["$File"]="$Match"
          else
              echo "No Result found in $File"
        fi
    done < <(find "$SearchPath" -type f -name '*.odt' -print0)
    echo "1" > "$SearchState"
}

dialog_error(){
    yad --title="$Title" \
      --center --width="400" --height="100" \
      --image=dialog-error \
      --window-icon=dialog-error \
      --class="$WMCLASS" \
      --text="$1" \
      --button="OK":0 2> /dev/null
}



dialog_progress(){
    sleep 0.5
    while true; do
      if [[ "$(cat "$SearchState")" = "1" ]]; then
        break
      else
        echo "#Searching..."
        sleep 0.5
      fi
    done | \
    yad --progress --pulsate --auto-close \
    --width=350 --height=100 \
    --title="$Title" \
    --text="Searching for '<b>$SearchTerm</b>' in '<b>$SearchPath</b>' ..." \
    --button='_Cancel!gtk-cancel!':1 \
    2> /dev/null
    PROG_RET="$?"
    if [[ "$PROG_RET" != "0" ]]
      then
          kill -s TERM "$TOP_PID"
    fi
}

dialog_results(){
    TxtMain="Search results for '<b>$SearchTerm</b>' in '<b>$SearchPath</b>'"

    if [[ -z "${Results[@]}" ]]; then
      dialog_error "$ErrNoReslt"
      exit 1
    fi

    for File in "${!Results[@]}"; do
      echo "$File"
      echo "Ubuntu Mono 12"
      echo "\"[...]${Results[$File]}[...]\""
    done | \
    yad --list --listen --print-column=1 \
    --expand−column=0 \
    --title="$Title" \
    --text="$TxtMain" \
    --ellipsize=NONE \
    --width=800 --height=600 --center \
    --dclick-action="bash -c \"open_result %s\" &" \
    --column="File":TEXT --column=@font@ --column="Result":TEXT
}

open_result(){
    xdg-open "$1"
}

# Prep

TOP_PID="$$"

SearchState="$(mktemp -u --tmpdir "${0##*/}.XXXXX")"
echo "0" > "$SearchState"

export -f open_result

# Cleanup

trap "echo "1" > "$SearchState"; sleep 1; [[ -f "$SearchState" ]] && rm -r "$SearchState"; exit" EXIT

# Main

dialog_options
dialog_progress&
odt_search
dialog_results

Dependencies

ODT finder uses unoconv to convert LO documents to plain text. The GUI is based on yad, a powerful Zenity fork. Yad isn't available in the official repositories, yet, but you can install it from a webupd8 PPA.

The following commands should take care of all dependencies:

sudo add-apt-repository ppa:webupd8team/y-ppa-manager
sudo apt-get update
sudo apt-get install unoconv yad

Installation

Copy and paste the contents of the code box above into a new text file, name it whatever you want and make it executable. You can integrate the script with your system in various ways, e.g. by assigning a launcher or using it as a Nautilus script.

Usage

First time launching the script you will be greeted with an entry dialog for the folder you want to search through and the search term:

enter image description here

Click on 'OK' to start the query. This might take a while:

enter image description here

When the result window pops up you can double-click on any of the entries to open it in your default viewer (LibreOffice, generally). You can do this for more than one file:

enter image description here

The script will exit after hitting OK, Cancel, or closing the window.

There are some basic checks to guide the user and warn them if something went wrong:

enter image description here

enter image description here

Hopefully this fits the bill ☺.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.