Skip to content
Snippets Groups Projects
Commit 7ed0a70a authored by Jason A. Donenfeld's avatar Jason A. Donenfeld
Browse files

find: add find/search command


This relies on a patched version of tree to work, unfortunately.
Hopefully upstream will accept our patch.

Signed-off-by: default avatarJason A. Donenfeld <Jason@zx2c4.com>
parent 7efccbc1
No related branches found
No related tags found
No related merge requests found
From 57f931a7a8564379e7b2e5c31301dcd6c0e84b50 Mon Sep 17 00:00:00 2001
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
Date: Thu, 4 Apr 2013 08:43:05 -0700
Subject: [PATCH] Add --matchdirs to check patterns against directories
This causes pattern matching to include the full contents of any
directories that match the pattern, including sub-directories.
---
doc/tree.1 | 10 +++++++++-
tree.c | 46 ++++++++++++++++++++++++++++++++++++++++------
2 files changed, 49 insertions(+), 7 deletions(-)
diff --git a/doc/tree.1 b/doc/tree.1
index 4b80852..7765f34 100644
--- a/doc/tree.1
+++ b/doc/tree.1
@@ -21,7 +21,7 @@
.SH NAME
tree \- list contents of directories in a tree-like format.
.SH SYNOPSIS
-\fBtree\fP [\fB-acdfghilnpqrstuvxACDFQNSUX\fP] [\fB-L\fP \fIlevel\fP [\fB-R\fP]] [\fB-H\fP \fIbaseHREF\fP] [\fB-T\fP \fItitle\fP] [\fB-o\fP \fIfilename\fP] [\fB--nolinks\fP] [\fB-P\fP \fIpattern\fP] [\fB-I\fP \fIpattern\fP] [\fB--inodes\fP] [\fB--device\fP] [\fB--noreport\fP] [\fB--dirsfirst\fP] [\fB--version\fP] [\fB--help\fP] [\fB--filelimit\fP \fI#\fP] [\fB--si\fP] [\fB--prune\fP] [\fB--du\fP] [\fB--timefmt\fP \fIformat\fP] [\fIdirectory\fP ...]
+\fBtree\fP [\fB-acdfghilnpqrstuvxACDFQNSUX\fP] [\fB-L\fP \fIlevel\fP [\fB-R\fP]] [\fB-H\fP \fIbaseHREF\fP] [\fB-T\fP \fItitle\fP] [\fB-o\fP \fIfilename\fP] [\fB--nolinks\fP] [\fB-P\fP \fIpattern\fP] [\fB-I\fP \fIpattern\fP] [\fB--inodes\fP] [\fB--device\fP] [\fB--noreport\fP] [\fB--dirsfirst\fP] [\fB--version\fP] [\fB--help\fP] [\fB--filelimit\fP \fI#\fP] [\fB--si\fP] [\fB--prune\fP] [\fB--du\fP] [\fB--timefmt\fP \fIformat\fP] [\fB--matchdirs\fP] [\fIdirectory\fP ...]
.br
.SH DESCRIPTION
\fITree\fP is a recursive directory listing program that produces a depth
@@ -123,6 +123,14 @@ Prints (implies -D) and formats the date according to the format string
which uses the \fBstrftime\fP(3) syntax.
.PP
.TP
+.B --matchdirs
+If a match pattern is specified by the -P option, this will cause the pattern
+to be applied to directory names (in addition to filenames). In the event of a
+match on the directory name, matching is disabled for the directory's
+contents.If the --prune option is used, empty folders that match the pattern
+will not be pruned.
+.PP
+.TP
.B -o \fIfilename\fP
Send output to \fIfilename\fP.
.PP
diff --git a/tree.c b/tree.c
index 19cf368..187613d 100644
--- a/tree.c
+++ b/tree.c
@@ -28,7 +28,7 @@ static char *hversion="\t\t tree v1.6.0 %s 1996 - 2011 by Steve Baker and Thomas
bool dflag, lflag, pflag, sflag, Fflag, aflag, fflag, uflag, gflag;
bool qflag, Nflag, Qflag, Dflag, inodeflag, devflag, hflag, Rflag;
bool Hflag, siflag, cflag, Xflag, duflag, pruneflag;
-bool noindent, force_color, nocolor, xdev, noreport, nolinks, flimit, dirsfirst, nosort;
+bool noindent, force_color, nocolor, xdev, noreport, nolinks, flimit, dirsfirst, nosort, matchdirs;
char *pattern = NULL, *ipattern = NULL, *host = NULL, *title = "Directory Tree", *sp = " ";
char *timefmt = NULL;
const char *charset = NULL;
@@ -75,12 +75,13 @@ int main(int argc, char **argv)
char sizebuf[64];
off_t size = 0;
mode_t mt;
+ bool needfulltree;
q = p = dtotal = ftotal = 0;
aflag = dflag = fflag = lflag = pflag = sflag = Fflag = uflag = gflag = FALSE;
Dflag = qflag = Nflag = Qflag = Rflag = hflag = Hflag = siflag = cflag = FALSE;
noindent = force_color = nocolor = xdev = noreport = nolinks = FALSE;
- dirsfirst = nosort = inodeflag = devflag = Xflag = FALSE;
+ matchdirs = dirsfirst = nosort = inodeflag = devflag = Xflag = FALSE;
duflag = pruneflag = FALSE;
flimit = 0;
dirs = xmalloc(sizeof(int) * (maxdirs=4096));
@@ -350,6 +351,11 @@ int main(int argc, char **argv)
Dflag = TRUE;
break;
}
+ if (!strncmp("--matchdirs",argv[i],11)) {
+ j = strlen(argv[i])-1;
+ matchdirs = TRUE;
+ break;
+ }
}
default:
fprintf(stderr,"tree: Invalid argument -`%c'.\n",argv[i][j]);
@@ -387,16 +393,17 @@ int main(int argc, char **argv)
parse_dir_colors();
initlinedraw(0);
+ needfulltree = duflag || pruneflag || matchdirs;
/* Set our listdir function and sanity check options. */
if (Hflag) {
- listdir = (duflag || pruneflag)? html_rlistdir : html_listdir;
+ listdir = needfulltree ? html_rlistdir : html_listdir;
Xflag = FALSE;
} else if (Xflag) {
- listdir = (duflag || pruneflag)? xml_rlistdir : xml_listdir;
+ listdir = needfulltree ? xml_rlistdir : xml_listdir;
colorize = FALSE;
colored = FALSE; /* Do people want colored XML output? */
} else {
- listdir = (duflag || pruneflag)? unix_rlistdir : unix_listdir;
+ listdir = needfulltree ? unix_rlistdir : unix_listdir;
}
if (dflag) pruneflag = FALSE; /* You'll just get nothing otherwise. */
@@ -534,6 +541,7 @@ void usage(int n)
" --charset X Use charset X for terminal/HTML and indentation line output.\n"
" --filelimit # Do not descend dirs with more than # files in them.\n"
" --timefmt <f> Print and format time according to the format <f>.\n"
+ " --matchdirs Include directory names in -P pattern matching.\n"
" -o filename Output to file instead of stdout.\n"
" -------- File options ---------\n"
" -q Print non-printable characters as '?'.\n"
@@ -689,6 +697,8 @@ struct _info **getfulltree(char *d, u_long lev, dev_t dev, off_t *size, char **e
struct _info **dir, **sav, **p, *sp;
struct stat sb;
int n;
+ u_long lev_tmp;
+ char *tmp_pattern = NULL, *start_rel_path;
*err = NULL;
if (Level >= 0 && lev > Level) return NULL;
@@ -696,7 +706,29 @@ struct _info **getfulltree(char *d, u_long lev, dev_t dev, off_t *size, char **e
stat(d,&sb);
dev = sb.st_dev;
}
+
+ // if the directory name matches, turn off pattern matching for contents
+ if (matchdirs && pattern) {
+ lev_tmp = lev;
+ for (start_rel_path = d + strlen(d); start_rel_path != d; --start_rel_path) {
+ if (*start_rel_path == '/')
+ --lev_tmp;
+ if (lev_tmp <= 0) {
+ if (*start_rel_path)
+ ++start_rel_path;
+ break;
+ }
+ }
+ if (patmatch(start_rel_path,pattern) == 1) {
+ tmp_pattern = pattern;
+ pattern = NULL;
+ }
+ }
sav = dir = read_dir(d,&n);
+ if (tmp_pattern) {
+ pattern = tmp_pattern;
+ tmp_pattern = NULL;
+ }
if (dir == NULL) {
*err = scopy("error opening dir");
return NULL;
@@ -745,7 +777,9 @@ struct _info **getfulltree(char *d, u_long lev, dev_t dev, off_t *size, char **e
saveino((*dir)->inode, (*dir)->dev);
(*dir)->child = getfulltree(path,lev+1,dev,&((*dir)->size),&((*dir)->err));
}
- if (pruneflag && (*dir)->child == NULL) {
+ // prune empty folders, unless they match the requested pattern
+ if (pruneflag && (*dir)->child == NULL &&
+ !(matchdirs && pattern && patmatch((*dir)->name,pattern) == 1)) {
sp = *dir;
for(p=dir;*p;p++) *p = *(p+1);
n--;
--
1.9.2
......@@ -72,6 +72,11 @@ by using the
.BR tree (1)
program. This command is alternatively named \fBlist\fP.
.TP
\fBfind\fP \fIpass-names\fP...
List names of passwords inside the tree that match \fIpass-names\fP by using the
.BR tree (1)
program. This command is alternatively named \fBsearch\fP.
.TP
\fBshow\fP [ \fI--clip\fP, \fI-c\fP ] \fIpass-name\fP
Decrypt and print a password named \fIpass-name\fP. If \fI--clip\fP or \fI-c\fP
is specified, do not print the password but instead copy the first line to the
......@@ -169,6 +174,25 @@ Password Store
.br
Alternatively, "\fBpass ls\fP".
.TP
Find existing passwords in store that match .com
.B zx2c4@laptop ~ $ pass find .com
.br
Search Terms: .com
.br
\[u251C]\[u2500]\[u2500] Business
.br
\[u2502] \[u251C]\[u2500]\[u2500] some-silly-business-site.com
.br
\[u2514]\[u2500]\[u2500] Email
.br
\[u251C]\[u2500]\[u2500] donenfeld.com
.br
\[u2514]\[u2500]\[u2500] zx2c4.com
.br
.br
Alternatively, "\fBpass search .com\fP".
.TP
Show existing password
.B zx2c4@laptop ~ $ pass Email/zx2c4.com
.br
......
......@@ -57,7 +57,7 @@ _pass()
{
COMPREPLY=()
local cur="${COMP_WORDS[COMP_CWORD]}"
local commands="init ls show insert generate edit rm git help version"
local commands="init ls find show insert generate edit rm git help version"
if [[ $COMP_CWORD -gt 1 ]]; then
local lastarg="${COMP_WORDS[$COMP_CWORD-1]}"
case "${COMP_WORDS[1]}" in
......
......@@ -106,3 +106,5 @@ complete -c $PROG -f -A -n '__fish_pass_uses_command git' -a 'commit' -d 'Commit
complete -c $PROG -f -A -n '__fish_pass_uses_command git' -a 'push' -d 'Push changes to remote repo'
complete -c $PROG -f -A -n '__fish_pass_uses_command git' -a 'pull' -d 'Pull changes from remote repo'
complete -c $PROG -f -A -n '__fish_pass_uses_command git' -a 'log' -d 'View changelog'
complete -c $PROG -f -A -n '__fish_pass_needs_command' -a find -d 'Command: find a password file or directory matching pattern'
......@@ -77,6 +77,7 @@ _pass () {
subcommands=(
"init:Initialize new password storage"
"ls:List passwords"
"find:Find password files or directories based on pattern"
"show:Decrypt and print a password"
"insert:Insert a new password"
"generate:Generate a new password using pwgen"
......
......@@ -43,6 +43,8 @@ usage() {
Optionally reencrypt existing passwords using new gpg-id.
$program [ls] [subfolder]
List passwords.
$program find pass-names...
List passwords that match pass-names.
$program [show] [--clip,-c] pass-name
Show existing password and optionally put it on the clipboard.
If put on the clipboard, it will be cleared in $CLIP_TIME seconds.
......@@ -71,7 +73,7 @@ usage() {
}
is_command() {
case "$1" in
init|ls|list|show|insert|edit|generate|remove|rm|delete|git|help|--help|version|--version) return 0 ;;
init|ls|list|find|search|show|insert|edit|generate|remove|rm|delete|git|help|--help|version|--version) return 0 ;;
*) return 1 ;;
esac
}
......@@ -268,6 +270,25 @@ case "$command" in
exit 1
fi
;;
find|search)
if [[ -z "$@" ]]; then
echo "Usage: $program $command pass-names..."
exit 1
fi
if ! tree --help |& grep -q "^ --matchdirs"; then
echo "ERROR: $program: incompatible tree command"
echo
echo "Your version of the tree command is missing the relevent patch to add the"
echo "--matchdirs switch. Please ask your distribution to patch your version of"
echo "tree with:"
echo " http://git.zx2c4.com/password-store/plain/contrib/tree-1.6.0-matchdirs.patch"
echo "Sorry for the inconvenience."
exit 1
fi
terms="$@"
echo "Search Terms: $terms"
tree -l --noreport -P "*${terms// /*|*}*" --prune --matchdirs "$PREFIX" | tail -n +2 | sed 's/\.gpg$//'
;;
insert)
multiline=0
noecho=1
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment