-
Notifications
You must be signed in to change notification settings - Fork 0
/
pick_file
executable file
·96 lines (81 loc) · 3.43 KB
/
pick_file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#!/bin/bash
#This script lets a user select a file to open by typing part of its
#name, kind of like Quicksilver (only lighter-weight). It's meant to
#be invoked by a shortcut key such as Windows-space.
#
#Depends on:
# dmenu
# locate / updatedb
# xdg-open
#Set this variable to the directory you want to open files in
DIRECTORY_TO_INCLUDE="$HOME"
TEMP_FILE="/tmp/filenames"
TEMP_DB="/tmp/files_db"
TEMP_RESULT="/tmp/result.txt"
make_files_db() {
#Create the database
#Unforunately there seems to be no good way to use updatedb to create just a single database with files from
#multiple different directories.
#There are 2 versions of updatedb, and GNU locate has an extra option --localpaths which lets you specify
#multiple paths with one command. mlocate, the version I'm using, doesn't.
#However, mlocate is apparently newer, and has the improvement that it reuses the old database
#to save time, and apparently if you install both then they'll both build their databases in the background.
updatedb -l 0 -U "$DIRECTORY_TO_INCLUDE" -o "$TEMP_DB" --prune-bind-mounts no
#Save only the filenames, not the full path, in the temporary file (see below for why).
#Skip hidden files.
#The "while read line" trick is like a for loop, but iterates over lines instead of space-delimited
#items. I found the trick here:
#http://ubergibson.com/article/iterating-through-lines-in-the-bash-shell
locate "$DIRECTORY_TO_INCLUDE" -d "$TEMP_DB" | grep -v "/\." | sed 's/.*\///' > "$TEMP_FILE"
}
if [ "$1" == "-r" ]
then
#User selected to rebuild the temporary file
make_files_db
echo "Temporary file rebuilt"
exit 0
elif [ ! -f "$TEMP_FILE" ]
then
echo "Building temporary file... (Use $0 -r to rebuild it - it's recommended to set this to happen regularly, e.g. daily or when your computer starts)"
make_files_db
fi
#Select a file to edit.
#The selection menu only displays the file's name here, not
#the full path.
#The reason for that is that otherwise there would be too many choices matching the letters you type -
#if the letters match a directory name, then all the files in that directory would also be included in the choices.
chosen_file=`cat "$TEMP_FILE" | dmenu -i`
open_file() {
#For many programs there's a benefit to setting the current directory to the directory of the file
cd `dirname $1`
#Open the file according to how they configured that type of file in their desktop environment
xdg-open "$1"
}
if [ -n "$chosen_file" ] #If a file was selected
then
#Prepend a / to increase the chances of matching only one file.
#The first grep is for directories, and ensures that only the directory itself is matched and not things in the directory.
#The second grep excludes hidden files.
locate -d "$TEMP_DB" /$chosen_file | grep "$chosen_file$" | grep -v "/\." > "$TEMP_RESULT"
#Count how many files have the filename that was selected.
lines=`cat "$TEMP_RESULT" | wc -l`
if [ "1" = "$lines" ]
then
#If there's exactly one file of that name, edit it.
#Get the full path of the file
full_file=`cat "$TEMP_RESULT"`
open_file "$full_file"
elif [ "0" = "$lines" ]
then
echo "Not found"
else
#There were multiple files that share the same filename.
#Ask the user which file they want to edit by displaying the full path
#this time.
full_file=`cat "$TEMP_RESULT" | dmenu -i -p "Which $chosen_file?"`
if [ -n "$full_file" ]
then
open_file "$full_file"
fi
fi
fi