3 // A shell utility for somewhat emulating the Tracker's "Find By Formula"
6 // by Ficus Kirkpatrick (ficus@ior.com)
8 // Modified by Jerome Duval on November 03, 2003
10 // Filtering capability added by Stefano Ceccherini on January 14, 2005
22 #include <VolumeRoster.h>
23 #include <SupportDefs.h>
26 #include "FilteredQuery.h"
28 extern const char *__progname
;
33 bool includeSubFolders
;
38 FilterByFolder(const entry_ref
*ref
, void *arg
)
40 folder_params
* params
= static_cast<folder_params
*>(arg
);
41 BPath
& wantedPath
= params
->path
;
42 bool includeSub
= params
->includeSubFolders
;
46 if (!strncmp(path
.Path(), wantedPath
.Path(),
47 strlen(wantedPath
.Path())))
50 if (path
.GetParent(&path
) == B_OK
&&
59 bool o_all_volumes
= false; // Query all volumes?
60 bool o_escaping
= true; // Escape metacharacters?
61 bool o_subfolders
= false;
66 printf("usage: %s [ -e ] [ -a || -v <path-to-volume> ] expression\n"
67 " -e\t\tdon't escape meta-characters\n"
68 " -p <path>\tsearch only in the given path\n"
69 " -s\t\tinclude subfolders (valid only if -p is used)\n"
70 " -a\t\tperform the query on all volumes\n"
71 " -v <file>\tperform the query on just one volume; <file> can be any\n"
72 "\t\tfile on that volume. Defaults to the current volume.\n"
73 " Hint: '%s name=foo' will find files named \"foo\"\n",
74 __progname
, __progname
);
80 perform_query(BVolume
&volume
, const char *predicate
, const char *filterpath
)
84 // Set up the volume and predicate for the query.
85 query
.SetVolume(&volume
);
86 query
.SetPredicate(predicate
);
87 if (filterpath
!= NULL
) {
88 folder_params options
;
89 options
.path
= filterpath
;
90 options
.includeSubFolders
= o_subfolders
;
91 query
.AddFilter(FilterByFolder
, &options
);
94 status_t status
= query
.Fetch();
95 if (status
== B_BAD_VALUE
) {
96 // the "name=" part may be omitted in our arguments
97 BString string
= "name=";
100 query
.SetPredicate(string
.String());
101 status
= query
.Fetch();
103 if (status
!= B_OK
) {
104 printf("query: bad query expression\n");
110 while (query
.GetNextEntry(&entry
) == B_OK
) {
111 if (entry
.GetPath(&path
) < B_OK
) {
112 fprintf(stderr
, "%s: could not get path for entry\n", __progname
);
116 printf("%s\n", o_escaping
?
117 BString().CharacterEscape(path
.Path(), " ()?*&\"'[]^\\~|;!<>*$", '\\').String()
124 main(int32 argc
, const char **argv
)
126 // Make sure we have the minimum number of arguments.
130 // Which volume do we make the query on?
131 // Default to the current volume.
132 char volumePath
[B_FILE_NAME_LENGTH
];
133 char directoryPath
[B_PATH_NAME_LENGTH
];
135 strcpy(volumePath
, ".");
136 strcpy(directoryPath
, ".");
138 // Parse command-line arguments.
140 while ((opt
= getopt(argc
, (char **)argv
, "eavsd:")) != -1) {
143 o_all_volumes
= true;
151 strncpy(volumePath
, optarg
, B_FILE_NAME_LENGTH
);
155 strncpy(directoryPath
, optarg
, B_PATH_NAME_LENGTH
);
170 if (!o_all_volumes
) {
171 // Find the volume that the query should be performed on,
172 // and set the query to it.
173 BEntry
entry(volumePath
);
174 if (entry
.InitCheck() != B_OK
) {
175 printf("query: %s is not a valid file\n", volumePath
);
179 status_t status
= entry
.GetVolume(&volume
);
180 if (status
!= B_OK
) {
181 fprintf(stderr
, "%s: could not get volume: %s\n", __progname
, strerror(status
));
185 if (!volume
.KnowsQuery())
186 printf("query: volume containing %s is not query-enabled\n", volumePath
);
188 perform_query(volume
, argv
[optind
], directoryPath
);
190 // Okay, we want to query all the disks -- so iterate over
191 // them, one by one, running the query.
192 BVolumeRoster volumeRoster
;
193 while (volumeRoster
.GetNextVolume(&volume
) == B_OK
) {
194 // We don't print errors here -- this will catch /pipe and
195 // other filesystems we don't care about.
196 if (volume
.KnowsQuery())
197 perform_query(volume
, argv
[optind
], directoryPath
);