summaryrefslogtreecommitdiffstats
path: root/README.md
blob: 41a8cb3ce459e320009f69c699717fc375498d46 (plain)
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
# fselect
Find files with SQL-like queries

[![Crates.io](https://img.shields.io/crates/v/fselect.svg)](https://crates.io/crates/fselect)
[![build](https://github.com/jhspetersson/fselect/actions/workflows/rust.yml/badge.svg)](https://github.com/jhspetersson/fselect/actions/workflows/rust.yml)

### Why use fselect?

While it doesn't tend to fully replace traditional `find` and `ls`, **fselect** has these nice features:

* SQL-like (not real SQL, but highly relaxed!) grammar easily understandable by humans
* complex queries
* aggregate, statistics, date, and other functions
* search within archives
* `.gitignore`, `.hgignore`, and `.dockerignore` support (experimental)
* search by width and height of images, EXIF metadata
* search by MP3 info
* search by extended file attributes
* search by file hashes
* search by MIME type
* shortcuts to common file types
* interactive mode
* various output formatting (CSV, JSON, and others)

More is under way!

### Installation

#### Latest release from source

* Install [Rust with Cargo](https://www.rust-lang.org/en-US/install.html) and its dependencies to build a binary
* Run `cargo install fselect`

#### Arch Linux

[AUR package](https://aur.archlinux.org/packages/fselect/), thanks to [@asm0dey](https://github.com/asm0dey)

#### NixOS

[`fselect` in `nixpkgs`](https://github.com/filalex77/nixpkgs/blob/1eced92263395896c10cea69e5f60e8be5f43aeb/pkgs/tools/misc/fselect/default.nix), thanks to [@filalex77](https://github.com/filalex77)

#### Other Linux

[Static build with musl](https://github.com/jhspetersson/fselect/releases/download/0.8.6/fselect-x86_64-linux-musl.gz).

#### Windows 64bit

A statically precompiled [binary](https://github.com/jhspetersson/fselect/releases/download/0.8.6/fselect-x86_64-win.zip) is available at Github downloads.

#### Windows via winget

* Install [winget](https://github.com/microsoft/winget-cli)
* Run `winget install -e --id fselect.fselect`

#### Windows via Chocolatey

* Install [Chocolatey](https://chocolatey.org/install)
* Run `choco install fselect`

#### Windows via Scoop

* Install [Scoop](https://scoop.sh)
* Run `scoop install fselect`

#### Mac via Homebrew

* Install [brew](https://brew.sh)
* Run `brew install fselect`

#### Mac via MacPorts

* Install [MacPorts](https://www.macports.org)
* Run:
  ```
  sudo port selfupdate
  sudo port install fselect
  ```

### Usage

    fselect [ARGS] COLUMN[, COLUMN...] [from ROOT[, ROOT...]] [where EXPR] [group by COLUMNS] [order by COLUMNS] [limit N] [into FORMAT]

### Interactive mode

    fselect -i

### Documentation

[More detailed description. Look at examples first.](docs/usage.md)

### Examples

Find temporary or config files (full path and size):

    fselect size, path from /home/user where name = '*.cfg' or name = '*.tmp'
    
Windows users may omit the quotes:

    fselect size, path from C:\Users\user where name = *.cfg or name = *.tmp

Or put all the arguments into the quotes like this:

    fselect "name from /home/user/tmp where size > 0"

Find files (just names) with any content (size > 0):

    fselect name from /home/user/tmp where size gt 0

Specify file size, get absolute path, and add it to the results:

    cd /home/user
    fselect size, abspath from ./tmp where size gt 2g
    fselect fsize, abspath from ./tmp where size = 5m
    fselect hsize, abspath from ./tmp where size lt 8k
    fselect name, size from ./tmp where size between 5mb and 6mb
    
More complex query:

    fselect "name from /tmp where (name = *.tmp and size = 0) or (name = *.cfg and size > 1000000)"
    
Aggregate functions (you can use curly braces if you want, and even combine them with the regular parentheses):

    fselect "MIN(size), MAX{size}, AVG(size), SUM{size}, COUNT(*) from /home/user/Downloads"
    
Formatting functions:

    fselect "LOWER(name), UPPER(name), LENGTH(name), YEAR(modified) from /home/user/Downloads"
    
Get the year of an oldest file:

    fselect "MIN(YEAR(modified)) from /home/user"
    
Use single quotes if you need to address files with spaces:

    fselect "path from '/home/user/Misc stuff' where name != 'Some file'"
    
Regular expressions of [Rust flavor](https://docs.rs/regex/1.1.0/regex/#syntax) are supported:

    fselect name from /home/user where path =~ '.*Rust.*'
    
Negate regular expressions:

    fselect "name from . where path !=~ '^\./config'"
    
Simple globs expand automatically and work with `=` and `!=` operators:

    fselect name from /home/user where path = '*Rust*'
    
Classic LIKE:

    fselect "path from /home/user where name like '%report-2018-__-__???'"
    
Exact match operators to search with regexps disabled:

    fselect "path from /home/user where name === 'some_*_weird_*_name'"
    
Find files by date:

    fselect path from /home/user where created = 2017-05-01
    fselect path from /home/user where modified = today
    fselect path from /home/user where accessed = yesterday
    fselect "path from /home/user where modified = 'apr 1'"
    fselect "path from /home/user where modified = 'last fri'"
    
Be more specific to match all files created at interval between 3PM and 4PM:

    fselect path from /home/user where created = '2017-05-01 15'
    
And even more specific:

    fselect path from /home/user where created = '2017-05-01 15:10'
    fselect path from /home/user where created = '2017-05-01 15:10:30'
    
Date and time intervals possible (find everything updated since May 1st):

    fselect path from /home/user where modified gte 2017-05-01
    
Default is current directory:

    fselect path, size where name = '*.jpg'
    
Search within multiple locations:

    fselect path from /home/user/oldstuff, /home/user/newstuff where name = '*.jpg'
    
With minimum and/or maximum depth specified (`depth` is a synonym for `maxdepth`):

    fselect path from /home/user/oldstuff depth 5 where name = '*.jpg'
    fselect path from /home/user/oldstuff mindepth 2 maxdepth 5, /home/user/newstuff depth 10 where name = '*.jpg'

Optionally follow symlinks:

    fselect path, size from /home/user symlinks where name = '*.jpg'
    
Search within archives (currently only zip-archives are supported):

    fselect path, size from /home/user archives where name = '*.jpg'
    
Or in combination:

    fselect size, path from /home/user depth 5 archives symlinks where name = '*.jpg' limit 100

Enable `.gitignore` or `.hgignore` support:

    fselect size, path from /home/user/projects gitignore where name = '*.cpp'
    fselect size, path from /home/user/projects hgignore where name = '*.py'        
    
Search by image dimensions:

    fselect CONCAT(width, 'x', height), path from /home/user/photos where width gte 2000 or height gte 2000
    
Find square images:
    
    fselect path from /home/user/Photos where width = height

Find images with a known name part but unknown extension:
    
    fselect path from /home/user/projects where name = "*RDS*" and width gte 1

Find old-school rap MP3 files:

    fselect duration, path from /home/user/music where genre = Rap and bitrate = 320 and mp3_year lt 2000  
    
Shortcuts to common file extensions:

    fselect path from /home/user where is_archive = true
    fselect path, mime from /home/user where is_audio = 1
    fselect path, mime from /home/user where is_book != false

Even simpler way of using boolean columns:

    fselect path from /home/user where is_doc
    fselect path from /home/user where is_image
    fselect path from /home/user where is_video
    
Find files with dangerous permissions:
    
    fselect mode, path from /home/user where other_write or other_exec
    fselect mode, path from /home/user where other_all
    
Simple glob-like expressions or even regular expressions on file mode are possible:
    
    fselect mode, path from /home/user where mode = '*rwx'
    fselect mode, path from /home/user where mode =~ '.*rwx$'
    
Find files by owner's uid or gid:

    fselect uid, gid, path from /home/user where uid != 1000 or gid != 1000
    
Or by owner's or group's name:

    fselect user, group, path from /home/user where user = mike or group = mike

Find special files:

    fselect name from /usr/bin where suid
    fselect path from /tmp where is_pipe
    fselect path from /tmp where is_socket
    
Find files with xattrs, check if particular xattr exists, or get its value:

    fselect "path, has_xattrs, has_xattr(user.test), xattr(user.test) from /home/user"
    
Include arbitrary text as columns:

    fselect "name, ' has size of ', size, ' bytes'"

Group results:

    fselect "ext, count(*) from /tmp group by ext"            

Order results:

    fselect path from /tmp order by size desc, name
    fselect modified, fsize, path from ~ order by 1 desc, 3
    
Finally limit the results:

    fselect name from /home/user/samples limit 5 
    
Format output:

    fselect size, path from /home/user limit 5 into json
    fselect size, path from /home/user limit 5 into csv
    fselect size, path from /home/user limit 5 into html

### License

MIT/Apache-2.0

---

Supported by [JetBrains IDEA](https://jb.gg/OpenSourceSupport) open source license