fd

Build Status Build status Version info English 中文

fdfind 를 대체할 수 있는 간단하고, 빠르고, 그리고 사용자 친화적인 commad line util이다.

이 fd는 find의 강력한 모든 기능을 지원하지 않지만, 주요 기능의 80%정도 지원하고 있다.

특징

  • 편리한 문법(syntax): find -iname '*PATTERN*'대신에 fd PATTERN.
  • Terminal에서 컬러풀한 결과(ls와 유사하게).
  • 빠른 속도 (참고: benchmarks).
  • Smart case: 기본적으로 case-insensitive한 검색을 지원한다. 패턴에 대문자가 포함되어 있으면 case-sensitive하게 변경된다*.
  • 숨김 폴더 및 파일은 무시(default).
  • .gitignore에서 설정한 내용은 무시(default).
  • 정규식 지원.
  • 유니코드(unicode) 지원.
  • Command가 find보다 50%정도 짧음 :-).
  • GNU 병렬과 유사한 문법(syntax)으로 병렬 실행 command 지원.

데모

Demo

벤치마크

벤치마크를 하기 위해 home 폴더 안에 있는 [0-9].jpg로 끝나는 파일을 검색할 것이다. Home 폴더에는 약 190,000개 이상 되는 하위 폴더들과 약 백 만개의 파일들이 있다. 또 벤치마크 결과를 분석(averaging and statistical analysis)하기 위해 hyperfine을 사용한다. 아래의 벤치마크 결과는 "warm"/pre-filled disck-cache 환경에서 수행한 결과다("cold" disk-cache 환경에서도 유사한 트랜드가 나타남).

find를 수행했을 때:

    Benchmark #1: find ~ -iregex '.*[0-9]\\.jpg$'
    
      Time (mean ± σ):      7.236 s ±  0.090 s
    
      Range (min … max):    7.133 s …  7.385 s

find는 정규식을 사용하지 않는 검색에서 꽤 빠른 결과를 보여주고 있다:

    Benchmark #2: find ~ -iname '*[0-9].jpg'
    
      Time (mean ± σ):      3.914 s ±  0.027 s
    
      Range (min … max):    3.876 s …  3.964 s

이제 fd를 이용해서 같은 작업을 해본다. 주의할 점은 fd 는 항상 정규식으로 검색한다. 옵션으로 넣은 --hidden--no-ignore은 위와 동일한 비교를 위해 필요했다. 왜냐하면 fd는 숨김 폴더들과 ignored 된 경로들을 기본적으로 검색하지 않기 때문이다(아래를 참고):

    Benchmark #3: fd -HI '.*[0-9]\\.jpg$' ~
    
      Time (mean ± σ):     811.6 ms ±  26.9 ms
    
      Range (min … max):   786.0 ms … 870.7 ms

위의 상황에서, fd가 대략적으로 find -iregex보다 9배, find -iname보다 5배나 더 빠른 성능을 보여주고 있다. 성능 차이가 나는 반면에 두개의 결과 모든 같은 결과를 보여주었다 😄.

끝으로, --hidden--no-ignore 옵션 없이 실행 해보자(물론 이 검색 결과는 위와 다르다). fd로 숨겨진 폴더 또는 git-ignored로 무시되는 것을 찾을 필요가 없다면, 훨씬 더 빠르다:

    Benchmark #4: fd '[0-9]\\.jpg$' ~
    
      Time (mean ± σ):     123.7 ms ±   6.0 ms
    
      Range (min … max):   118.8 ms … 140.0 ms

Note: 이 벤치마크는 하나의 특정 machine에서 진행한 결과이다. 꽤 많은 테스트(아래에 계속되는 테스트 결과)를 진행했지만, 이 결과는 다른 machine에서의 결과와 다를 수 있다! 다른 사람들이 이 테스트를 자신의 컴퓨터에서 테스트를 해보는 것을 기대한다. 필요한 모든 스크립트는 이 this repository를 참고하자.

Concerning fd's speed, the main credit goes to the regex and ignore crates that are also used in ripgrep (check it out!).

컬러풀한 결과

fdls처럼 extension으로 결과를 컬러풀하게 나타낼 수 있다. 컬러풀하게 표현하기 위해서는 LS_COLORS라는 환경 변수가 반드시 설정되어 있어야 한다. 일반적으로 이 값은 dircolors에 의해 설정된다. dircolors라는 command는 다른 형식의 파일을 색깔로 구분하기 위해 편리한 설정 포맷을 제공하고 있다. 보편적으로 LS_COLORS는 이미 설정되어 있다. 만약 다른 색상 또는 더 이쁜 색상을 설정하고 싶다면, here 또는 here를 참고하자.

fdNO_COLOR 환경 변수도 존중한다.

병렬 Command 실행

Command에 -x/ --exec라는 옵션이 있다면, 병렬로 command를 수행하기 위한 job pool이 생성될 것이다. 문법은 GNU 병렬 처리와 유사하다:

  • {}: 검색 결과의 경로로 대체되는 플레이스 홀더(documents/images/party.jpg).
  • {.}: {}와 비슷하나 파일의 확장자가 없는 플레이스 홀더(documents/images/party).
  • {/}: 검색 결과의 basename로 대체되는 플레이스 홀더(party.jpg).
  • {//}: 찾은 경로의 상위(부모) 경로를 이용하는 플레이스 홀더(documents/images).
  • {/.}: 파일 확장자가 제거된 basename을 사용하는 플레이스 홀더(party).
# Convert all jpg files to png files:
fd -e jpg -x convert {} {.}.png

# Unpack all zip files (if no placeholder is given, the path is appended):
fd -e zip -x unzip

# Convert all flac files into opus files:
fd -e flac -x ffmpeg -i {} -c:a libopus {.}.opus

# Count the number of lines in Rust files (the command template can be terminated with ';'):
fd -x wc -l \; -e rs

Command를 실행하기 위한 쓰레드(thread)의 수는 --threads/ -j옵션으로 설정할 수 있다.

설치

On Ubuntu

... and other Debian-based Linux distributions.

If you run Ubuntu 19.04 (Disco Dingo) or newer, you can install the officially maintained package:

sudo apt install fd-find

Note that the binary is called fdfind as the binary name fd is already used by another package. It is recommended that you add an alias fd=fdfind to your shells initialization file, in order to use fd in the same way as in this documentation.

If you use an older version of Ubuntu, you can download the latest .deb package from the release page and install it via:

sudo dpkg -i fd_7.5.0_amd64.deb  # adapt version number and architecture

On Debian

If you run Debian Buster or newer, you can install the officially maintained Debian package:

sudo apt-get install fd-find

Note that the binary is called fdfind as the binary name fd is already used by another package. It is recommended that you add an alias fd=fdfind to your shells initialization file, in order to use fd in the same way as in this documentation.

On Fedora

Starting with Fedora 28, you can install fd from the official package sources:

dnf install fd-find

For older versions, you can use this Fedora copr to install fd:

dnf copr enable keefle/fd
dnf install fd

On Alpine Linux

You can install the fd package from the official sources, provided you have the appropriate repository enabled:

apk add fd

On Arch Linux

You can install the fd package from the official repos:

pacman -S fd

On Gentoo Linux

You can use the fd ebuild from the official repo:

emerge -av fd

On openSUSE Linux

You can install the fd package from the official repo:

zypper in fd

On Void Linux

You can install fd via xbps-install:

xbps-install -S fd

On macOS

You can install fd with Homebrew:

brew install fd

… or with MacPorts:

sudo port install fd

On Windows

You can download pre-built binaries from the release page.

Alternatively, you can install fd via Scoop:

scoop install fd

Or via Chocolatey:

choco install fd

On NixOS / via Nix

You can use the Nix package manager to install fd:

nix-env -i fd

On FreeBSD

You can install the fd-find package from the official repo:

pkg install fd-find

From NPM

On linux and macOS, you can install the fd-find package:

npm install -g fd-find

From source

With Rust's package manager cargo, you can install fd via:

cargo install fd-find

Note that rust version 1.36.0 or later is required.

From binaries

The release page includes precompiled binaries for Linux, macOS and Windows.

Development

git clone https://github.com/sharkdp/fd

# Build
cd fd
cargo build

# Run unit tests and integration tests
cargo test

# Install
cargo install

Command-line options

USAGE:
    fd [FLAGS/OPTIONS] [<pattern>] [<path>...]

FLAGS:
    -H, --hidden            Search hidden files and directories
    -I, --no-ignore         Do not respect .(git|fd)ignore files
        --no-ignore-vcs     Do not respect .gitignore files
    -s, --case-sensitive    Case-sensitive search (default: smart case)
    -i, --ignore-case       Case-insensitive search (default: smart case)
    -g, --glob              Glob-based search (default: regular expression)
    -F, --fixed-strings     Treat the pattern as a literal string
    -a, --absolute-path     Show absolute instead of relative paths
    -L, --follow            Follow symbolic links
    -p, --full-path         Search full path (default: file-/dirname only)
    -0, --print0            Separate results by the null character
    -h, --help              Prints help information
    -V, --version           Prints version information

OPTIONS:
    -d, --max-depth <depth>            Set maximum search depth (default: none)
    -t, --type <filetype>...           Filter by type: file (f), directory (d), symlink (l),
                                       executable (x), empty (e)
    -e, --extension <ext>...           Filter by file extension
    -x, --exec <cmd>                   Execute a command for each search result
    -X, --exec-batch <cmd>             Execute a command with all search results at once
    -E, --exclude <pattern>...         Exclude entries that match the given glob pattern
    -c, --color <when>                 When to use colors: never, *auto*, always
    -S, --size <size>...               Limit results based on the size of files.
        --changed-within <date|dur>    Filter by file modification time (newer than)
        --changed-before <date|dur>    Filter by file modification time (older than)

ARGS:
    <pattern>    the search pattern - a regular expression unless '--glob' is used (optional)
    <path>...    the root directory for the filesystem search (optional)

This is the output of fd -h. To see the full set of command-line options, use fd --help which also includes a much more detailed help text.

튜토리얼

우선, command line의 모든 옵션들을 개괄적으로 알아보기 위해, 두 개의 command를 사용할 수 있다. 간략하게 메시지를 보기 위해서는 fd -h, 더 상세한 메세지를 보기 위해서는 fd --help.

간단하게 검색하기

fd는 파일시스템(filesystem)의 모든 것을 찾기 위해 만들어졌다. 가장 기본적인 검색 방법은 검색 패턴(search pattern)을 이용하여 fd를 실행하는 것이다. 예를 들어, netflix라는 이름이 포함된 오래된 script를 찾는다고 하자:

> fd netfl
Software/python/imdb-ratings/netflix-details.py

위와 같이 검색 패턴을 주어 command를 실행하면, fd는 현재 폴더부터 재귀적으로 netfl라는 패턴이 포함된 모든 것들을 검색한다.

정규 표현식으로 검색하기

검색 패턴은 정규 표현식으로 처리한다. 여기서 우리는 x로 시작하고 rc로 끝나는 모든 것을 검색해보자:

> cd /etc
> fd '^x.*rc$'
X11/xinit/xinitrc
X11/xinit/xserverrc

상위 폴더 지정해서 검색하기

특정 폴더에서 검색하고 싶다면, fd에 두 번째 매개변수(argument)로 넘겨줄 수 있다:

> fd passwd /etc
/etc/default/passwd
/etc/pam.d/passwd
/etc/passwd

어떠한 매개변수 없이 fd 실행하기

fd는 어떠한 매개변수 없이 실행할 수 있다. 이 방법은 재귀적으로(ls -R과 유사하게) 아주 빠르게 현재 폴더의 모든 것을 보는데에 아주 유용하다:

> cd fd/tests
> fd
testenv
testenv/mod.rs
tests.rs

주어진 폴더 밑의 모든 파일들을 보는 기능을 사용하고 싶다면, .^같은 catch-all 패턴을 이용해야 한다:

> fd . fd/tests/
testenv
testenv/mod.rs
tests.rs

특정 확장자로 검색하기

때때로, 특정 확장자의 모든 파일들을 찾고 싶을 수 있다. 이때는 -e(or --extension)라는 옵션을 이용할 수 있다. fd 저장소(repository)에 있는 곳에서 마크다운 확장자의 모든 파일을 찾아 보자:

> cd fd
> fd -e md
CONTRIBUTING.md
README.md

-e라는 옵션은 검색 패턴과 조합하여 사용할 수 있다:

> fd -e rs mod
src/fshelper/mod.rs
src/lscolors/mod.rs
tests/testenv/mod.rs

숨김, 무시되는 파일들

기본적으로 fd는 숨김 폴더, 파일들을 검색하지 않는다. 따라서 숨겨진 파일 또는 폴더를 찾기 위해서, -H (or --hideen) 옵션을 이용한다:

> fd pre-commit
> fd -H pre-commit
.git/hooks/pre-commit.sample

Git 저장소(또는 Git 저장소들을 포함하는 폴더)에서 작업을 한다면, fd는 .gitignore의 패턴에 매칭되는 것을 검색하지 않는다. 위와 마찬가지로 이 기능을 비활성하기 위해, -I (or --no-ignore) 옵션을 이용한다:

> fd num_cpu
> fd -I num_cpu
target/debug/deps/libnum_cpus-f5ce7ef99006aa05.rlib

즉, 모든 파일, 폴더들을 검색하기 위해서는 간단하게 위의 두 옵션을 조합하여 검색한다(-HI).

특정 폴더 및 파일들을 제외하기

가끔 우리는 특정 하위 폴더의 검색 결과를 제외하고 싶을 수 있다.
예를 들어, .git에 있는 모든 것을 제외하고 -H 옵션을 이용해 모든 숨김 파일, 폴더들을 찾는다고 하자. 이때 -E (or --exclude) 옵션을 사용할 수 있는데, 이 옵션은 arbitary glob 패턴으로 매개변수를 입력 받는다:

> fd -H -E .git …

또한 이렇게 마운트 된 폴더들을 제외할 수 있다:

> fd -E /mnt/external-drive …

.. 또는 특정 파일 형식을 제외할 수 있다:

> fd -E '*.bak'

이러한 제외 패턴들을 지속적으로 저장할 수 있는데, 이때 .fdignore 파일을 이용할 수 있다. 이 파일은 .gitignore파일과 비슷하게 동작하는데, fd에 한정되어 있다. 예를 들어:

> cat ~/.fdignore
/mnt/external-drive
*.bak

Note: 또한 fdrgag와 같은 다른 프로그램에서 사용하는 .ignore 파일을 지원한다.

xargs 또는 parallel와 함께 사용하기

모든 검색 결과들을 활용하고 싶다면, xargs에 결과를 전달(pipe)할 수 있다:

> fd -0 -e rs | xargs -0 wc -l

여기서 -0 옵션은 fd에게 NULL(개행 대신에)문자로 검색 결과를 구분하도록 한다. 이와 같은 방식으로 xargs-0 옵션도 NULL 문자로 구분하여 입력을 받도록 한다.

파일들을 삭제하기

검색 패턴에 충족하는 모든 파일 또는 폴더를 삭제하는데, fd를 이용할 수 있다. 만약 파일들만 삭제하기를 원한다면, --exec-batch/ -X 옵션을 이용하여 rm을 실행할 수 있다. 예를 들어, 재귀적으로 모든 .DS_Store 파일을 삭제하기 위해서는 다음과 같이 실행한다:

> fd -H '^\.DS_Store$' -tf -X rm

삭제하기 전에 결과를 보고 싶다면, -X rm 옵션을 주지 않고 fd를 실행해보자. 아니면 다른 방법으로 "interactive"라는 rm의 옵션을 이용하자:

> fd -H '^\.DS_Store$' -tf -X rm -i

또, 폴더를 삭제하고 싶다면, 같은 방법으로 제거할 수 있다. rm--recursive/ -r 옵션을 이용해 폴더를 삭제할 수 있다.

Note: fd … -X rm -r와 같은 명령어를 실행할 때, race conditions을 초래할 수 있다: 예를 들자면, …/foo/bar/foo/…와 같이 폴더가 존재하고, foo라는 모든 폴더를 삭제한다고 하자. 이때 먼저 부모 경로의 foo폴더가 삭제되고 난 후, rm을 수행한다면 "'foo/bar/foo': No such file or directory" 라는 에러가 나타는 상황을 만나게 될 것이다.

Troubleshooting

fd로 파일이 정상적으로 찾을 수 없다면?!

기본적으로 fd는 숨김 파일, 폴더들은 검색하지 않는 것을 기억하자. 또 .gitignore의 패턴에 만족하는 것들을 무시한다. 반드시 가능한 모든 파일을 찾고 싶다면, -H-I라는 옵션을 이용해 두 기능을 비활성화 하자.

> fd -HI …

fd에서 정규식 패턴이 정상적으로 동작하지 않는다면?!

많은 특수 문자([], ^, $, ... 처럼)는 쉘(shell)에서도 특수 문자들이다. 의심스럽다면, 정규식 패턴을 single quote(')로 감싸서 사용하자:

> fd '^[A-Z][0-9]+$'

만약 dash(-)로 시작하는 패턴을 사용한다면, 반드시 command 끝에 --을 옵션에 추가해야한다. 그러면 command의 옵션으로 그 패턴이 정상 동작할 것이다. 또 다른 방법으로는 hyphen(-)을 character class로 사용하자:

> fd -- '-pattern'
> fd '[-]pattern'

다른 프로그램들과 통합하기

fzf와 함께 fd 사용하기

fuzz finder fzf의 입력을 fd를 이용해 생성할 수 있다:

export FZF_DEFAULT_COMMAND='fd --type file'
export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND"

위와 같이 설정한 후에 fd 결과를 검색하고 fzf를 사용하기 위해 터미널에서 vim <Ctrl-T>를 입력할 수 있다..

또 숨김 파일들과 심볼릭 링크 파일들을 포함하고 싶을 수 있다:

export FZF_DEFAULT_COMMAND='fd --type file --follow --hidden --exclude .git'

설정에 의해 fzf 안에서도 컬러풀하게 fd의 결과를 볼 수 있다.

export FZF_DEFAULT_COMMAND="fd --type file --color=always"
export FZF_DEFAULT_OPTS="--ansi"

더 상세한 내용은 fzf REAME에 있는 Tips section을 참고하자

emacs와 함께 fd 사용하기

emacs의 패키지인 find-file-in-project도 파일들을 찾기 위해 fd를 사용할 수 있다.

find-file-in-project을 설치한 후에, (setq ffip-use-rust-fd t)~/.emacs 또는 ~/.emacs.d/init.el 파일에 추가하자.

emacs에서는 파일들을 찾기 위해, M-x find-file-in-project-by-selected을 실행 해보자. 또, 프로젝트의 모든 파일을 보기 위해서는 M-x find-file-in-project을 실행 해보자.

License

Copyright (c) 2017-2020 The fd developers

fd is distributed under the terms of both the MIT License and the Apache License 2.0.

See the LICENSE-APACHE and LICENSE-MIT files for license details.