Files
kashav--fsql/README.md
T
2026-07-13 10:22:17 +00:00

348 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- 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 [![Go](https://github.com/kashav/fsql/actions/workflows/go.yml/badge.svg)](https://github.com/kashav/fsql/actions/workflows/go.yml)
>使用类 SQL 查询在你的文件系统中进行搜索。
## 目录
- [演示](#demo)
- [安装](#installation)
- [用法](#usage)
- [查询语法](#query-syntax)
- [示例](#usage-examples)
- [贡献](#contribute)
- [许可证](#license)
## 演示
[![fsql.gif](./media/fsql.gif)](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) 发布。