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

find: support tree 1.7.0

parent 95d10093
No related branches found
No related tags found
No related merge requests found
......@@ -23,7 +23,7 @@ Depends on:
http://sourceforge.net/projects/xclip/
- pwgen
http://sourceforge.net/projects/pwgen/
- tree
- tree >= 1.7.0
http://mama.indstate.edu/users/ice/tree/
- GNU getopt
http://www.kernel.org/pub/linux/utils/util-linux/
......
From 59d7a2237500c9439b758910e951bcd5dc48c657 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 and --caseinsensitive to matching
The new --matchdirs option causes pattern matching to include
the full contents of any directories that match the pattern,
including sub-directories.
The --caseinsensitive option simply makes pattern matching case
insensitive.
---
CHANGES | 5 ++++
README | 4 ++++
doc/tree.1 | 17 +++++++++++++-
tree.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++-----------
4 files changed, 91 insertions(+), 14 deletions(-)
diff --git a/CHANGES b/CHANGES
index 10f2e20..004b86a 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,8 @@
+Version 1.6.1
+ - Added --matchdirs flag so that patterns match against directory names and
+ then subsequently descend into sub-directories.
+ - Added --caseinsensitive flag so patterns match without regards to case.
+
Version 1.6.0
- Re-org of code into multiple files, split HTML and Unix listdir() into
separate functions, various code cleanups and optimizations.
diff --git a/README b/README
index ab58d82..58767e8 100644
--- a/README
+++ b/README
@@ -141,6 +141,10 @@ Ujjwal Kumar
- Suggested that tree backslash spaces like ls does for script use. Made
output more like ls.
+Jason A. Donenfeld
+ - Added --matchdirs flag for matching patterns against directories.
+ - Added --caseinsensitive flag for case insensitive pattern matching.
+
And many others whom I've failed to keep track of. I should have started
this list years ago.
diff --git a/doc/tree.1 b/doc/tree.1
index 4b80852..41d0815 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--caseinsensitive\fP] [\fB--matchdirs\fP] [\fIdirectory\fP ...]
.br
.SH DESCRIPTION
\fITree\fP is a recursive directory listing program that produces a depth
@@ -123,6 +123,19 @@ Prints (implies -D) and formats the date according to the format string
which uses the \fBstrftime\fP(3) syntax.
.PP
.TP
+.B --caseinsensitive
+If a match pattern is specified by the -P option, this will cause the pattern
+to match without regards to the case of each letter.
+.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
@@ -314,6 +327,8 @@ Steve Baker (ice@mama.indstate.edu)
HTML output hacked by Francesc Rocher (rocher@econ.udg.es)
.br
Charsets and OS/2 support by Kyosuke Tokoro (NBG01720@nifty.ne.jp)
+.br
+Directory and case matching by Jason A. Donenfeld (Jason@zx2c4.com)
.SH BUGS AND NOTES
Tree does not prune "empty" directories when the -P and -I options are used by
diff --git a/tree.c b/tree.c
index 19cf368..388aae5 100644
--- a/tree.c
+++ b/tree.c
@@ -19,16 +19,17 @@
#include "tree.h"
-static char *version ="$Version: $ tree v1.6.0 (c) 1996 - 2011 by Steve Baker, Thomas Moore, Francesc Rocher, Kyosuke Tokoro $";
-static char *hversion="\t\t tree v1.6.0 %s 1996 - 2011 by Steve Baker and Thomas Moore <br>\n"
+static char *version ="$Version: $ tree v1.6.0 (c) 1996 - 2014 by Steve Baker, Thomas Moore, Francesc Rocher, Kyosuke Tokoro, Jason A. Donenfeld $";
+static char *hversion="\t\t tree v1.6.0 %s 1996 - 2014 by Steve Baker and Thomas Moore <br>\n"
"\t\t HTML output hacked and copyleft %s 1998 by Francesc Rocher <br>\n"
- "\t\t Charsets / OS/2 support %s 2001 by Kyosuke Tokoro\n";
+ "\t\t Charsets / OS/2 support %s 2001 by Kyosuke Tokoro <br>\n"
+ "\t\t Directory and case matching %s 2014 by Jason A. Donenfeld\n";
/* Globals */
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, caseinsensitive;
char *pattern = NULL, *ipattern = NULL, *host = NULL, *title = "Directory Tree", *sp = " ";
char *timefmt = NULL;
const char *charset = NULL;
@@ -75,12 +76,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;
+ caseinsensitive = matchdirs = dirsfirst = nosort = inodeflag = devflag = Xflag = FALSE;
duflag = pruneflag = FALSE;
flimit = 0;
dirs = xmalloc(sizeof(int) * (maxdirs=4096));
@@ -350,6 +352,16 @@ int main(int argc, char **argv)
Dflag = TRUE;
break;
}
+ if (!strncmp("--matchdirs",argv[i],11)) {
+ j = strlen(argv[i])-1;
+ matchdirs = TRUE;
+ break;
+ }
+ if (!strncmp("--caseinsensitive",argv[i],17)) {
+ j = strlen(argv[i])-1;
+ caseinsensitive = TRUE;
+ break;
+ }
}
default:
fprintf(stderr,"tree: Invalid argument -`%c'.\n",argv[i][j]);
@@ -387,16 +399,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. */
@@ -517,7 +530,8 @@ void usage(int n)
"usage: tree [-acdfghilnpqrstuvxACDFQNSUX] [-H baseHREF] [-T title ] [-L level [-R]]\n"
"\t[-P pattern] [-I pattern] [-o filename] [--version] [--help] [--inodes]\n"
"\t[--device] [--noreport] [--nolinks] [--dirsfirst] [--charset charset]\n"
- "\t[--filelimit[=]#] [--si] [--timefmt[=]<f>] [<directory list>]\n");
+ "\t[--filelimit[=]#] [--si] [--timefmt[=]<f>] [--matchdirs]\n"
+ "\t[--caseinsensitive] [<directory list>]\n");
if (n < 2) exit(0);
fprintf(stderr,
" ------- Listing options -------\n"
@@ -534,6 +548,8 @@ 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"
+ " --caseinsensitive Match files without regards to case 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 +705,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 +714,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 +785,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--;
@@ -869,8 +911,19 @@ char *gnu_getcwd()
}
/*
+ * Returns a lower case version of the argument if case insensitive
+ * mode is enabled. Note that this is static and inline so that we
+ * do not incur penalty when this is running in a tight loop.
+ */
+static inline char cond_lower(char c)
+{
+ return caseinsensitive ? tolower(c) : c;
+}
+
+/*
* Patmatch() code courtesy of Thomas Moore (dark@mama.indstate.edu)
* '|' support added by David MacMahon (davidm@astron.Berkeley.EDU)
+ * Case insensitive support added by Jason A. Donenfeld (Jason@zx2c4.com)
* returns:
* 1 on a match
* 0 on a mismatch
@@ -918,11 +971,11 @@ int patmatch(char *buf, char *pat)
pat += 2;
if(*pat == '\\' && *pat)
pat++;
- if(*buf >= m && *buf <= *pat)
+ if(cond_lower(*buf) >= cond_lower(m) && cond_lower(*buf) <= cond_lower(*pat))
match = n;
if(!*pat)
pat--;
- } else if(*buf == *pat) match = n;
+ } else if(cond_lower(*buf) == cond_lower(*pat)) match = n;
pat++;
}
buf++;
@@ -940,7 +993,7 @@ int patmatch(char *buf, char *pat)
if(*pat)
pat++;
default:
- match = (*buf++ == *pat);
+ match = (cond_lower(*buf++) == cond_lower(*pat));
break;
}
pat++;
--
1.9.2
......@@ -331,7 +331,7 @@ cmd_show() {
else
echo "${path%\/}"
fi
tree -l --noreport "$PREFIX/$path" | tail -n +2 | sed 's/\.gpg$//'
tree -C -l --noreport "$PREFIX/$path" | tail -n +2 | sed 's/\.gpg$//'
else
echo "$path is not in the password store."
exit 1
......@@ -343,21 +343,9 @@ cmd_find() {
echo "Usage: $PROGRAM $COMMAND pass-names..."
exit 1
fi
if ! tree --version | grep -q "Jason A. Donenfeld"; then
cat <<-_EOF
Error: incompatible tree command.
Your version of the tree command is missing the relevent patch to add the
--matchdirs and --caseinsensitive switches. Please ask your distribution
to patch your version of tree with:
http://git.zx2c4.com/password-store/plain/contrib/tree-1.6.0-matchdirs.patch
Sorry for the inconvenience.
_EOF
exit 1
fi
local terms="$@"
echo "Search Terms: $terms"
tree -l --noreport -P "*${terms// /*|*}*" --prune --matchdirs --caseinsensitive "$PREFIX" | tail -n +2 | sed 's/\.gpg$//'
tree -C -l --noreport -P "*${terms// /*|*}*" --prune --matchdirs --ignore-case "$PREFIX" | tail -n +2 | sed 's/\.gpg$//'
}
cmd_grep() {
......
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