浏览代码

simplify stest

master
Connor Lane Smith 12 年前
父节点
当前提交
8cc28cb426
共有 3 个文件被更改,包括 53 次插入62 次删除
  1. +2
    -4
      dmenu_run
  2. +7
    -8
      stest.1
  3. +44
    -50
      stest.c

+ 2
- 4
dmenu_run 查看文件

@@ -5,10 +5,8 @@ if [ ! -d "`dirname "$CACHE"`" ]; then
fi
(
IFS=:
if ls -d $PATH | stest -q -n "$CACHE"; then
for dir in $PATH; do
ls $dir | stest -C $dir -fx
done | sort -u > "$CACHE"
if stest -dqr -n "$CACHE" $PATH; then
stest -flx $PATH | sort -u > "$CACHE"
fi
)
cmd=`dmenu "$@" < "$CACHE"` && exec sh -c "$cmd"

+ 7
- 8
stest.1 查看文件

@@ -3,9 +3,7 @@
stest \- filter a list of files by properties
.SH SYNOPSIS
.B stest
.RB [ -bcdefghpqrsuwx ]
.RB [ -C
.IR dir ]
.RB [ -abcdefghlpqrsuwx ]
.RB [ -n
.IR file ]
.RB [ -o
@@ -15,13 +13,11 @@ stest \- filter a list of files by properties
.B stest
takes a list of files and filters by the files' properties, analogous to
.IR test (1).
Files which pass all tests are printed to stdout. If no files are given as
arguments, stest will read a list of files from stdin, one path per line.
Files which pass all tests are printed to stdout.
.SH OPTIONS
.TP
.BI \-C " dir"
Tests files relative to directory
.IR dir .
.B \-a
Test hidden files.
.TP
.B \-b
Test that files are block specials.
@@ -44,6 +40,9 @@ Test that files have their set-group-ID flag set.
.B \-h
Test that files are symbolic links.
.TP
.B \-l
Test the contents of a directory given as an argument.
.TP
.BI \-n " file"
Test that files are newer than
.IR file .


+ 44
- 50
stest.c 查看文件

@@ -1,4 +1,5 @@
/* See LICENSE file for copyright and license details. */
#include <dirent.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -6,80 +7,73 @@
#include <unistd.h>
#include <sys/stat.h>

#define OPER(x) (oper[(x)-'a'])
#define FLAG(x) (flag[(x)-'a'])

static bool test(const char *);
static void test(const char *, const char *);

static bool quiet = false;
static bool oper[26];
static bool match = false;
static bool flag[26];
static struct stat old, new;

int
main(int argc, char *argv[]) {
char buf[BUFSIZ], *p;
bool match = false;
struct dirent *d;
char buf[BUFSIZ];
DIR *dir;
int opt;

while((opt = getopt(argc, argv, "C:bcdefghn:o:pqrsuwx")) != -1)
while((opt = getopt(argc, argv, "abcdefghln:o:pqrsuwx")) != -1)
switch(opt) {
case 'C': /* tests relative to directory */
if(chdir(optarg) == -1) {
perror(optarg);
exit(2);
}
break;
case 'n': /* newer than file */
case 'o': /* older than file */
if(!(OPER(opt) = stat(optarg, (opt == 'n' ? &new : &old)) == 0))
if(!(FLAG(opt) = !stat(optarg, (opt == 'n' ? &new : &old))))
perror(optarg);
break;
case 'q': /* quiet (no output, just status) */
quiet = true;
break;
default: /* miscellaneous operators */
OPER(opt) = true;
FLAG(opt) = true;
break;
case '?': /* error: unknown flag */
fprintf(stderr, "usage: %s [-bcdefghpqrsuwx] [-C dir] [-n file] [-o file] [file...]\n", argv[0]);
fprintf(stderr, "usage: %s [-abcdefghlpqrsuwx] [-n file] [-o file] [file...]\n", argv[0]);
exit(2);
}
if(optind == argc)
while(fgets(buf, sizeof buf, stdin)) {
if(*(p = &buf[strlen(buf)-1]) == '\n')
*p = '\0';
match |= test(buf);
for(; optind < argc; optind++)
if(FLAG('l') && (dir = opendir(argv[optind]))) {
/* test directory contents */
while((d = readdir(dir)))
if(snprintf(buf, sizeof buf, "%s/%s", argv[optind], d->d_name) < sizeof buf)
test(buf, d->d_name);
closedir(dir);
}
else
while(optind < argc)
match |= test(argv[optind++]);
else
test(argv[optind], argv[optind]);

return match ? 0 : 1;
}

bool
test(const char *path) {
struct stat st;
void
test(const char *path, const char *name) {
struct stat st, ln;

if((!OPER('b') || (stat(path, &st) == 0 && S_ISBLK(st.st_mode))) /* block special */
&& (!OPER('c') || (stat(path, &st) == 0 && S_ISCHR(st.st_mode))) /* character special */
&& (!OPER('d') || (stat(path, &st) == 0 && S_ISDIR(st.st_mode))) /* directory */
&& (!OPER('e') || (access(path, F_OK) == 0)) /* exists */
&& (!OPER('f') || (stat(path, &st) == 0 && S_ISREG(st.st_mode))) /* regular file */
&& (!OPER('g') || (stat(path, &st) == 0 && (st.st_mode & S_ISGID))) /* set-group-id flag */
&& (!OPER('h') || (lstat(path, &st) == 0 && S_ISLNK(st.st_mode))) /* symbolic link */
&& (!OPER('n') || (stat(path, &st) == 0 && st.st_mtime > new.st_mtime)) /* newer than file */
&& (!OPER('o') || (stat(path, &st) == 0 && st.st_mtime < old.st_mtime)) /* older than file */
&& (!OPER('p') || (stat(path, &st) == 0 && S_ISFIFO(st.st_mode))) /* named pipe */
&& (!OPER('r') || (access(path, R_OK) == 0)) /* readable */
&& (!OPER('s') || (stat(path, &st) == 0 && st.st_size > 0)) /* not empty */
&& (!OPER('u') || (stat(path, &st) == 0 && (st.st_mode & S_ISUID))) /* set-user-id flag */
&& (!OPER('w') || (access(path, W_OK) == 0)) /* writable */
&& (!OPER('x') || (access(path, X_OK) == 0))) { /* executable */
if(quiet)
if(!stat(path, &st) && !lstat(path, &ln)
&& ( FLAG('a') || name[0] != '.') /* hidden */
&& (!FLAG('b') || S_ISBLK(st.st_mode)) /* block special */
&& (!FLAG('c') || S_ISCHR(st.st_mode)) /* character special */
&& (!FLAG('d') || S_ISDIR(st.st_mode)) /* directory */
&& (!FLAG('e') || access(path, F_OK) == 0) /* exists */
&& (!FLAG('f') || S_ISREG(st.st_mode)) /* regular file */
&& (!FLAG('g') || st.st_mode & S_ISGID) /* set-group-id flag */
&& (!FLAG('h') || (!lstat(path, &ln) && S_ISLNK(ln.st_mode))) /* symbolic link */
&& (!FLAG('n') || st.st_mtime > new.st_mtime) /* newer than file */
&& (!FLAG('o') || st.st_mtime < old.st_mtime) /* older than file */
&& (!FLAG('p') || S_ISFIFO(st.st_mode)) /* named pipe */
&& (!FLAG('r') || access(path, R_OK) == 0) /* readable */
&& (!FLAG('s') || st.st_size > 0) /* not empty */
&& (!FLAG('u') || st.st_mode & S_ISUID) /* set-user-id flag */
&& (!FLAG('w') || access(path, W_OK) == 0) /* writable */
&& (!FLAG('x') || access(path, X_OK) == 0)) { /* executable */
if(FLAG('q'))
exit(0);
puts(path);
return true;
match = true;
puts(name);
}
else
return false;
}

正在加载...
取消
保存