0

TL;DR

Here is the default behavior.

find ~/ -name *.git 2>/dev/null | dmenu
# Searches everything in home directory and shows output

Time taken about 1-2 sec

What I want:

find ~/ -name *.git 2>/dev/null | less
# Show as soon as it finds result. How to get similar output in dmenu?

As files in my PC will increase, this is going to take longer time.

Detailed description:

I am piping input into dmenu from a find command which takes about 1-2 seconds. Is it possible for dmenu to show input as soon as there is some input in the pipe. Because that's the basic working of piping. It seems like dmenu waits until there are all the entries in pipe so that user can search from it which also looks legit, but still can this be avoided? I would like to run dmenu as soon as there is input in buffer.

Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
  • Not necessarily all entries, but as many entries until the stdout from `find` gets flushed. In theory you would need the stdout being unbuffered. I have not tried this yet, but if this is Linux, or MacOS with the Gnu Coreutils installed, I would try [this](https://stackoverflow.com/questions/3465619/how-to-make-output-of-any-shell-command-unbuffered#25548995) approach. – user1934428 Jun 01 '20 at 07:11
  • I am using it on a Linux machine. `stdbuf -i0 -o0 -e0 find ~/ -name *.git 2>/dev/null | dmenu` takes same amount of time and so does `find ~/ -name *.git 2>/dev/null | stdbuf -i0 -o0 -e0 dmenu`. (didn't know which is correct so tried both ways!) – Chinmay Chhajed Jun 01 '20 at 07:25
  • Since you want to unbuffer `find`, the former one looks more sensible for me, but I would combine both, just for a try: Doing the stdout from `find` unbuffered, and the stdin fron `dmenu`. – user1934428 Jun 01 '20 at 07:30
  • Thinking of it .... Of course if `dmenu` itself chooses to swallow the whole input before doing something, there isn't anything you can do, unless `dmenu` itself provides an option to change this behaviour, because this is then not related to buffering anymore. – user1934428 Jun 01 '20 at 07:33

1 Answers1

0

I found some workaround to decrease time against find here. Instead of find, locate can be used. So the command goes like

locate -r '/home'"$USER"'.*\.git$'

-r takes input a regular expression. Arguments to -r here filters all git repositories inside /home/$USER. This is a bit faster than using find.

Catch using locate

locate uses a local database for searching. So it will only work as expected when local database will be built/updated.

To update database, use sudo updatedb. Whenever you add/move/delete a file (or a directory in this case), remember to update database for locate to give proper results.

Tip

To avoid entering password every time for updatedb (and other frequently used commands), add them to sudoers by executing sudo visudo and adding entry for path to command's binary's location

Update

I recently realized why use locate when I can simply maintain my own database and cat all the entries to dmenu. With this I was able to achieve what I needed.

# Make a temp directory
 mkdir -p $HOME/.tmp
# Search for all git directories and store them in ~/.tmp/gitfies. 
[ -e $HOME/.tmp/gitfiles ] || find $HOME/ -regex .*/\.git$ -type d 2>/dev/null > $HOME/.tmp/gitfiles
# cat this file into dmenu
cat $HOME/.tmp/gitfiles | dmenu

This gives a fuzzy finding for directories with dmenu. This is better than using locate as even in locate you need to update local database and so in here. Since we do the filtering of git files at runtime with locate, it is a bit slower than this case.

I can simple create an alias to update this database analogous to sudo updatedb in case of locate, by

alias gitdbupdate="find $HOME/ -regex .*/\.git$ -type d 2>/dev/null > $HOME/.tmp/gitfiles"

Note that I am not using /tmp/ as it won't be persistent across power cycles. So rather I create my own $HOME/.tmp/ directory.

Community
  • 1
  • 1
  • Or add yourself to the `wheel` group (or `sudo` group on some distros) and then uncomment the final line (or next to final line) using `# visudo` to allows `wheel` group members to execute any command without a password. (there is a similar 2-line addition to `/etc/pam.d/su` to allow members of `wheel` to `su` without a password) – David C. Rankin Jun 11 '20 at 06:43