348 lines
9.5 KiB
Markdown
348 lines
9.5 KiB
Markdown
<!-- WEHUB_ZH_README -->
|
||
> [!NOTE]
|
||
> 本文档由 WeHub 基于上游 README 翻译整理,属于社区翻译,非官方中文文档。
|
||
> [English](./README.en.md) · [原始项目](https://github.com/kashav/fsql) · [上游 README](https://github.com/kashav/fsql/blob/HEAD/README.md)
|
||
> 原作者、版权与许可证归属以原始项目及本仓库 LICENSE 文件为准。
|
||
|
||
# fsql [](https://github.com/kashav/fsql/actions/workflows/go.yml)
|
||
|
||
>使用类 SQL 查询在你的文件系统中进行搜索。
|
||
|
||
## 目录
|
||
|
||
- [演示](#demo)
|
||
- [安装](#installation)
|
||
- [用法](#usage)
|
||
- [查询语法](#query-syntax)
|
||
- [示例](#usage-examples)
|
||
- [贡献](#contribute)
|
||
- [许可证](#license)
|
||
|
||
## 演示
|
||
|
||
[](https://asciinema.org/a/120534)
|
||
|
||
## 安装
|
||
|
||
#### 二进制文件
|
||
|
||
[查看最新发布版本](https://github.com/kashav/fsql/releases/latest).
|
||
|
||
#### 通过 Go 安装
|
||
|
||
```sh
|
||
$ go get -u -v github.com/kashav/fsql/...
|
||
$ which fsql
|
||
$GOPATH/bin/fsql
|
||
```
|
||
|
||
#### 通过 Homebrew 安装
|
||
|
||
```sh
|
||
$ brew install fsql
|
||
$ which fsql
|
||
/usr/local/bin/fsql
|
||
```
|
||
|
||
#### 手动构建
|
||
|
||
```sh
|
||
$ git clone https://github.com/kashav/fsql.git $GOPATH/src/github.com/kashav/fsql
|
||
$ cd $_ # $GOPATH/src/github.com/kashav/fsql
|
||
$ make
|
||
$ ./fsql
|
||
```
|
||
|
||
## 用法
|
||
|
||
fsql 期望通过 stdin 接收单个查询。你也可以选择以交互模式使用 fsql。
|
||
|
||
使用 `-help` 标志查看用法说明。
|
||
|
||
```sh
|
||
$ fsql -help
|
||
usage: fsql [options] [query]
|
||
-v print version and exit (shorthand)
|
||
-version
|
||
print version and exit
|
||
```
|
||
|
||
## 查询语法
|
||
|
||
一般来说,每条查询都需要一个 `SELECT` 子句(用于指定要显示哪些属性)、一个 `FROM` 子句(用于指定要搜索哪些目录)和一个 `WHERE` 子句(用于指定要测试的条件)。
|
||
|
||
```console
|
||
>>> SELECT attribute, ... FROM source, ... WHERE condition;
|
||
```
|
||
|
||
你可以选择省略 `SELECT` 和 `WHERE` 子句。
|
||
|
||
如果你通过 stdin 提供查询,则**不**需要引号,但你必须转义*保留*字符(例如 `*`、`<`、`>` 等)。
|
||
|
||
### 属性
|
||
|
||
当前支持的属性包括 `name`、`size`、`time`、`hash`、`mode`。
|
||
|
||
使用 `all` 或 `*` 来选择全部;如果未提供属性,则默认选择此项。
|
||
|
||
**示例**:
|
||
|
||
每组都包含一组等效的子句。
|
||
|
||
```console
|
||
>>> SELECT name, size, time ...
|
||
>>> name, size, time ...
|
||
```
|
||
|
||
```console
|
||
>>> SELECT all FROM ...
|
||
>>> all FROM ...
|
||
>>> FROM ...
|
||
```
|
||
|
||
### 源
|
||
|
||
每个源都应是计算机上某个目录的相对或绝对路径。
|
||
|
||
源路径可以包含环境变量(例如 `$GOPATH`)或波浪号(`~`)。使用连字符(`-`)来排除目录。源路径还支持使用 [glob 模式](https://en.wikipedia.org/wiki/Glob_(programming)).
|
||
|
||
如果某个目录以连字符开头(例如 `-foo`),请使用以下方式将其包含为源:
|
||
|
||
```console
|
||
>>> ... FROM ./-foo ...
|
||
```
|
||
|
||
**示例**:
|
||
|
||
```console
|
||
>>> ... FROM . ...
|
||
```
|
||
|
||
```console
|
||
>>> ... FROM ~/Desktop, ./*/**.go ...
|
||
```
|
||
|
||
```console
|
||
>>> ... FROM $GOPATH, -.git/ ...
|
||
```
|
||
|
||
### 条件
|
||
|
||
#### 条件语法
|
||
|
||
单个条件由 3 部分组成:属性、运算符和值。
|
||
|
||
- **属性**:
|
||
|
||
有效属性是以下任意一项:`name`、`size`、`mode`、`time`。
|
||
|
||
- **运算符**:
|
||
|
||
每个属性都有一组关联的运算符。
|
||
|
||
- `name`:
|
||
|
||
| 运算符 | 说明 |
|
||
| :---: | --- |
|
||
| `=` | 字符串相等 |
|
||
| `<>` / `!=` | 与使用 `"NOT ... = ..."` 同义 |
|
||
| `IN` | 基本列表包含 |
|
||
| `LIKE` | 简单模式匹配。使用 `%` 匹配零个、一个或多个字符。检查字符串是否以某值开头:`<value>%`,以某值结尾:`%<value>`,或包含某值:`%<value>%`。 |
|
||
| `RLIKE` | 使用正则表达式进行模式匹配。 |
|
||
|
||
- `size` / `time`:
|
||
|
||
- 所有基本代数运算符:`>`、`>=`、`<`、`<=`、`=`,以及 `<>` / `!=`。
|
||
|
||
- `hash`:
|
||
|
||
- `=` 或 `<>` / `!=`
|
||
|
||
- `mode`:
|
||
|
||
- `IS`
|
||
|
||
|
||
- **值**:
|
||
|
||
如果值包含空格,请用引号(单引号或双引号)或反引号将值括起来。
|
||
|
||
`size` 的默认单位是字节。
|
||
|
||
`time` 的默认格式是 `MMM DD YYYY HH MM`(例如 `"Jan 02 2006 15 04"`)。
|
||
|
||
使用 `mode` 来测试文件是否为普通文件(`IS REG`),或是否为目录(`IS DIR`)。
|
||
|
||
使用 `hash` 来计算和/或比较文件的哈希值。默认算法是 `SHA1`
|
||
|
||
#### 合取 / 析取
|
||
|
||
使用 `AND` / `OR` 来连接条件。请注意,优先级按出现顺序分配。
|
||
|
||
这意味着 `WHERE a AND b OR c` **不**等同于 `WHERE c OR b AND a`。使用括号来规避这一行为,即 `WHERE a AND b OR c` **等同**于 `WHERE c OR (b AND a)`。
|
||
|
||
**示例**:
|
||
|
||
```console
|
||
>>> ... WHERE name = main.go OR size = 5 ...
|
||
```
|
||
|
||
```console
|
||
>>> ... WHERE name = main.go AND size > 20 ...
|
||
```
|
||
|
||
#### 否定
|
||
|
||
使用 `NOT` 来否定条件。此关键字**必须**位于条件之前(例如 `... WHERE NOT a ...`)。
|
||
|
||
请注意,当前不支持对括号括起的条件进行否定。不过,你可以通过对查询应用 [德摩根定律(De Morgan's laws)](https://en.wikipedia.org/wiki/De_Morgan%27s_laws) 来轻松解决这一问题。例如,`... WHERE NOT (a AND b) ...` 在*逻辑上*等同于 `... WHERE NOT a OR NOT b ...`(由于 [惰性求值(lazy evaluation)](https://en.wikipedia.org/wiki/Lazy_evaluation)).,后者实际上更优)。
|
||
|
||
**示例**:
|
||
|
||
```console
|
||
>>> ... WHERE NOT name = main.go ...
|
||
```
|
||
|
||
### 属性修饰符
|
||
|
||
属性修饰符用于指定输入和输出值应如何处理。这些函数直接应用于 `SELECT` 和 `WHERE` 子句中的属性。
|
||
|
||
下表列出了当前支持的修饰符。请注意,`FORMAT` 的第一个参数始终是属性名称。
|
||
|
||
| 属性 | 修饰符 | 支持于 `SELECT` | 支持于 `WHERE` |
|
||
| :---: | --- | :---: | :---: |
|
||
| `hash` | `SHA1(, n)` | ✔️ | ✔️ |
|
||
| `name` | `UPPER`(与 `FORMAT(, UPPER)` 同义) | ✔️ | ✔️ |
|
||
| | `LOWER`(与 `FORMAT(, LOWER)` 同义) | ✔️ | ✔️ |
|
||
| | `FULLPATH` | ✔️ | |
|
||
| | `SHORTPATH` | ✔️ | |
|
||
| `size` | `FORMAT(, unit)` | ✔️ | ✔️ |
|
||
| `time` | `FORMAT(, layout)` | ✔️ | ✔️ |
|
||
|
||
|
||
- **`n`**:
|
||
|
||
指定哈希值的长度。使用负整数或 `ALL` 来显示所有数字。
|
||
|
||
- **`unit`**:
|
||
|
||
指定大小单位。可选:`B`(字节)、`KB`(千字节)、`MB`(兆字节)或 `GB`(千兆字节)。
|
||
|
||
- **`layout`**:
|
||
|
||
指定时间布局。可选:[`ISO`](https://en.wikipedia.org/wiki/ISO_8601),、[`UNIX`](https://en.wikipedia.org/wiki/Unix_time), 或 [自定义(custom)](https://golang.org/pkg/time/#Time.Format). 自定义布局必须参照以下日期提供:`Mon Jan 2 15:04:05 -0700 MST 2006`。
|
||
|
||
**示例**:
|
||
|
||
```console
|
||
>>> SELECT SHA1(hash, 20) ...
|
||
```
|
||
|
||
```console
|
||
>>> ... WHERE UPPER(name) ...
|
||
```
|
||
|
||
```console
|
||
>>> SELECT FORMAT(size, MB) ...
|
||
```
|
||
|
||
```console
|
||
>>> ... WHERE FORMAT(time, "Mon Jan 2 2006 15:04:05") ...
|
||
```
|
||
|
||
### 子查询
|
||
|
||
子查询允许编写更复杂的条件语句。这些查询在解析时会被递归求值。当前不支持在子查询中 SELECT 多个属性;如果提供了多个属性(或 `all`),则只会使用第一个属性。
|
||
|
||
引用外层查询的功能尚未实现,如果你想为此提供帮助,请参阅 [#4](https://github.com/kashav/fsql/issues/4)。
|
||
|
||
**示例**:
|
||
|
||
```console
|
||
>>> ... WHERE name IN (SELECT name FROM ../foo) ...
|
||
```
|
||
|
||
## 用法示例
|
||
|
||
列出主目录中每个目录的所有属性(请注意转义的 `*`):
|
||
|
||
```console
|
||
$ fsql SELECT \* FROM ~ WHERE mode IS DIR
|
||
```
|
||
|
||
列出 Desktop 和 Downloads 目录中名称包含 `csc` 的所有文件的名称:
|
||
|
||
```console
|
||
$ fsql "SELECT name FROM ~/Desktop, ~/Downloads WHERE name LIKE %csc%"
|
||
```
|
||
|
||
列出当前目录中也存在于其他某个目录中的所有文件:
|
||
|
||
```console
|
||
$ fsql
|
||
>>> SELECT all FROM . WHERE name IN (
|
||
... SELECT name FROM ~/Desktop/files.bak/
|
||
... );
|
||
```
|
||
|
||
通过 stdin 传递不带引号的查询有点麻烦,希望接下来的示例能说明这一点,我的建议是:如果你要使用子查询或属性修饰符,请使用交互模式,或将查询用引号括起来。
|
||
|
||
列出 `$GOPATH` 中名为 `main.go`、大于 10.5 千字节或小于 100 字节的所有文件:
|
||
|
||
```console
|
||
$ fsql SELECT all FROM $GOPATH WHERE name = main.go AND \(FORMAT\(size, KB\) \>= 10.5 OR size \< 100\)
|
||
$ fsql "SELECT all FROM $GOPATH WHERE name = main.go AND (FORMAT(size, KB) >= 10.5 OR size < 100)"
|
||
$ fsql
|
||
>>> SELECT
|
||
... all
|
||
... FROM
|
||
... $GOPATH
|
||
... WHERE
|
||
... name = main.go
|
||
... AND (
|
||
... FORMAT(size, KB) >= 10.5
|
||
... OR size < 100
|
||
... )
|
||
... ;
|
||
```
|
||
|
||
列出当前目录中在 2017 年 4 月 1 日之后修改过的 JavaScript 文件的名称、大小和修改时间:
|
||
|
||
```console
|
||
$ fsql SELECT UPPER\(name\), FORMAT\(size, KB\), FORMAT\(time, ISO\) FROM . WHERE name LIKE %.js AND time \> \'Apr 01 2017 00 00\'
|
||
$ fsql "SELECT UPPER(name), FORMAT(size, KB), FORMAT(time, ISO) FROM . WHERE name LIKE %.js AND time > 'Apr 01 2017 00 00'"
|
||
$ fsql
|
||
>>> SELECT
|
||
... UPPER(name),
|
||
... FORMAT(size, KB),
|
||
... FORMAT(time, ISO)
|
||
... FROM
|
||
... .
|
||
... WHERE
|
||
... name LIKE %.js
|
||
... AND time > 'Apr 01 2017 00 00'
|
||
... ;
|
||
```
|
||
|
||
## 贡献
|
||
|
||
本项目完全开源,欢迎[提交 Issue](https://github.com/kashav/fsql/issues) 或[发起 Pull Request(拉取请求)](https://github.com/kashav/fsql/pulls).
|
||
|
||
提交代码前,请确保测试通过且 linter 检查无问题。以下命令可能对你有所帮助,请参阅 [Makefile](./Makefile) 了解它们的作用。
|
||
|
||
```sh
|
||
$ make install \
|
||
get-tools
|
||
$ make fmt \
|
||
vet \
|
||
lint
|
||
$ make test \
|
||
coverage
|
||
$ make bootstrap-dist \
|
||
dist
|
||
```
|
||
|
||
## 许可证
|
||
|
||
fsql 源代码遵循 [MIT 许可证](./LICENSE) 发布。
|