Tuesday, September 30, 2008

再说find action,提高终端下的工作效率

再说find的action,是个很有用的工具,

对于查看目录下的所有文件,普通人常用的是ls,不带任何参数的ls,碰到有子目录的情况,就cd到子目录里面,进去只为敲个ls,再又cd回来,因为当前还是主要工作目录,需要查看哪个目录时就cd到哪儿去;进阶一点的人会用ls后接目录参数,可是ls还是只能列出一个目录,对于需要同时查看多个目录的情况可以用"ls -R",可是它只列出了文件名,没有全路径,对于下一步的最大可能是cat或调用编辑器,有了全路径才是最有用的;

试试这个: "find -ls"

一次将目录下所有文件都以ls方式列表出来,可以是递归的方式看到所有文件的"ls -l"方式的结果,并且有了全路径,可以用鼠标双击全选中,再敲中键(就是鼠标滚轮)便会粘贴出来,C-A定位光标到达行首,加上个cat或者vim,阅读或者是编辑,一切操作都是连贯的;

在Shell应用中,对/proc/sys/或/sys/下的查看常常既有列表还需要阅读变量内容,以前的做法是:

find /proc/sys/vm -type f -ls -exec cat {} \;

或者需要监视这个变量值的变化情况,加上个watch,每隔1s重读一次:

watch -n1 'find /proc/sys/vm -type f -printf "%p\t" -exec cat {} \;'

find是一个简单而强大的工具,绝不只是如名称一般只有"查找"文件的功用,它的参数有两个基本类型:


  1. test是一个条件判断,如查按文件名查找使用"-name ...";

  2. action是对找到的文件的一个动作,如缺省的-print是打印全路径名,-ls是模拟ls方式列表;



缺省的action只有ls,printf等,(printf另有强大的功能),而-exec扩展方式可以后接程序执行,如上面的-exec cat读出文件内容,

但是-exec cat实在太常用了,今日作了一个patch,在find-4.5.2上面加上-cat这个action,这样上面的监视命令就可以简化为:

find /proc/sys/vm -cat



Download as text

  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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
---
find/defs.h | 1 +
find/parser.c | 22 ++++++++++++++++++++++
find/pred.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
find/tree.c | 1 +
4 files changed, 76 insertions(+)

Index: findutils-4.5.2/find/defs.h
===================================================================
--- findutils-4.5.2.orig/find/defs.h
+++ findutils-4.5.2/find/defs.h
@@ -411,6 +411,7 @@ PREDICATEFUNCTION pred_cnewer;
PREDICATEFUNCTION pred_comma;
PREDICATEFUNCTION pred_ctime;
PREDICATEFUNCTION pred_delete;
+PREDICATEFUNCTION pred_cat;
PREDICATEFUNCTION pred_empty;
PREDICATEFUNCTION pred_exec;
PREDICATEFUNCTION pred_execdir;
Index: findutils-4.5.2/find/parser.c
===================================================================
--- findutils-4.5.2.orig/find/parser.c
+++ findutils-4.5.2/find/parser.c
@@ -91,6 +91,7 @@ static boolean parse_cnewer PARAM
static boolean parse_comma PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
static boolean parse_daystart PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
static boolean parse_delete PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
+static boolean parse_cat PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
static boolean parse_d PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
static boolean parse_depth PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
static boolean parse_empty PARAMS((const struct parser_table*, char *argv[], int *arg_ptr));
@@ -253,6 +254,7 @@ static struct parser_table const parse_t
{ARG_TEST, "ctime", parse_time, pred_ctime}, /* POSIX */
PARSE_POSOPT ("daystart", daystart), /* GNU */
PARSE_ACTION ("delete", delete), /* GNU, Mac OS, FreeBSD */
+ PARSE_ACTION ("cat", cat), /* GNU */
PARSE_OPTION ("d", d), /* Mac OS X, FreeBSD, NetBSD, OpenBSD, but deprecated in favour of -depth */
PARSE_OPTION ("depth", depth), /* POSIX */
PARSE_TEST ("empty", empty), /* GNU */
@@ -801,6 +803,26 @@ parse_delete (const struct parser_table*
}

static boolean
+parse_cat (const struct parser_table* entry, char *argv[], int *arg_ptr)
+{
+ struct predicate *our_pred;
+ (void) argv;
+ (void) arg_ptr;
+
+ our_pred = insert_primary (entry);
+ our_pred->side_effects = our_pred->no_default_print = true;
+ our_pred->need_stat = our_pred->need_type = false;
+ our_pred->est_success_rate = 1.0f;
+ open_stdout(&our_pred->args.printf_vec);
+
+#ifdef DEBUG
+ fprintf(stderr, "%s(%s:%d) called.\n", __func__, __FILE__, __LINE__);
+#endif
+
+ return true;
+}
+
+static boolean
parse_depth (const struct parser_table* entry, char **argv, int *arg_ptr)
{
(void) entry;
Index: findutils-4.5.2/find/pred.c
===================================================================
--- findutils-4.5.2.orig/find/pred.c
+++ findutils-4.5.2/find/pred.c
@@ -445,6 +445,58 @@ pred_delete (const char *pathname, struc
}

boolean
+pred_cat (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
+{
+ FILE * stream = pred_ptr->args.printf_vec.stream;
+ FILE * input_stream;
+ char buf[BUFSIZ];
+ int fd;
+ size_t read_len;
+
+ (void) pred_ptr;
+ (void) stat_buf;
+
+#ifdef DEBUG
+ fprintf(stderr, "%s(%s:%d) called.\n", __func__, __FILE__, __LINE__);
+#endif
+
+ if ((fd = openat(state.cwd_dir_fd, state.rel_pathname, O_RDONLY
+#if defined O_LARGEFILE
+ |O_LARGEFILE
+#endif
+ )) <>
+ {
+ error (0, errno, "%s", safely_quote_err_filename(0, pathname));
+ state.exit_status = 1;
+ return false;
+ }
+
+ input_stream = fdopen(fd, "r");
+ if (input_stream == NULL)
+ {
+ error (0, errno, "%s", safely_quote_err_filename(0, pathname));
+ state.exit_status = 1;
+ return false;
+ }
+
+ while ((read_len = fread(buf, 1, sizeof buf, input_stream)) > 0)
+ {
+#ifdef DEBUG
+ fprintf(stderr, "%s(%s:%d): read_len = %d, stream = %p\n",
+ __func__, __FILE__, __LINE__, read_len, stream);
+#endif
+ fwrite(buf, 1, read_len, stream);
+
+ if (read_len <>
+ break;
+ }
+
+ fclose(input_stream);
+
+ return true;
+}
+
+boolean
pred_empty (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
{
(void) pathname;
Index: findutils-4.5.2/find/tree.c
===================================================================
--- findutils-4.5.2.orig/find/tree.c
+++ findutils-4.5.2/find/tree.c
@@ -906,6 +906,7 @@ static struct pred_cost_lookup costlooku
{ pred_comma , NeedsNothing, },
{ pred_ctime , NeedsStatInfo, },
{ pred_delete , NeedsSyncDiskHit },
+ { pred_cat , NeedsNothing },
{ pred_empty , NeedsStatInfo },
{ pred_exec , NeedsEventualExec },
{ pred_execdir , NeedsEventualExec },



Download as text


参看这个帖子来个实用的:查看文件链接,回复find命令的人是我:有人需要一些shell功能,想到了用python去写,想法不错,却没想到的是,那一段的python代码只对应了一行find命令。

No comments: