- Notifications
You must be signed in to change notification settings - Fork149
⚡ A new cd command that helps you navigate faster by learning your habits.
License
skywind3000/z.lua
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
A command line tool which helps you navigate faster by learning your habits ⚡
An alternative toz.sh with windows and posix shells support and various improvements.
z.lua is a faster way to navigate your filesystem. It tracks your most used directories, based on 'frecency'. After a short learning phase, z will take you to the most 'frecent' directory that matches ALL of the regexes given on the command line, in order.
For example,z foo bar would match/foo/bar but not/bar/foo.
From people using z.lua:
- I like this in principal. I’m pretty damn predictable at the command line and far too lazy to make shortcuts
- It feels far more intuitive and it's so incredibly convenient to be able to jump between folders I'm working in without having to traverse an entire tree. The shell used to feel so constraining for me, but tools like this are making me enjoy it so much more.
- I can finally have autojump-like functionality on my Raspberry Pi 1 without waiting 30 seconds every time I open a new shell. Thanks z.lua devs.
- Anyway, z.lua is a promising project. If you only need directory jumping, it may be the best choice.
- 10x times faster thanfasd andautojump,3x times faster thanz.sh.
- Gain the ultimate speed with an optionalnative module written in C.
- Available forposix shells: bash, zsh, dash, sh, ash, ksh, busybox and etc.
- Available for Fish Shell, Nushell, Power Shell and Windows cmd.
- Enhanced matching algorithm takes you to where ever you want precisely.
- Allow updating database only if
$PWDchanged with "$_ZL_ADD_ONCE" set to 1. - Interactive selection enables you to choose where to go before cd.
- Integrated with FZF (optional) for interactive selection and completion.
- Quickly go back to a parent directory instead of typing "cd ../../..".
- Corresponding experience in different shells and operating systems.
- Compatible with Lua (5.1, 5.2, 5.3+) and luajit.
- Self contained, distributed as a single
z.luascript, no other dependence.
z foo# cd to most frecent dir matching fooz foo bar# cd to most frecent dir matching foo and barz -r foo# cd to the highest ranked dir matching fooz -t foo# cd to most recently accessed dir matching fooz -l foo# list matches instead of cdz -c foo# restrict matches to subdirs of $PWDz -e foo# echo the best match, don't cdz -i foo# cd with interactive selectionz -I foo# cd with interactive selection using fzfz -b foo# cd to the parent directory starting with fooz -b foo bar# replace foo with bar in cwd and cd there
Bash:
put something like this in your
.bashrc:eval "$(lua /path/to/z.lua --init bash)"the default matching algorithm is similar to z.sh to keep compatible, you may like the enhanced matching algorithm for productivity:
eval "$(lua /path/to/z.lua --init bash enhanced once)"and perhaps this:
eval "$(lua /path/to/z.lua --init bash enhanced once echo)"if you want
z.luaprint the new directory after cd.For
fzftab completion use:eval "$(lua /path/to/z.lua --init bash enhanced once fzf)"NixOS users using home-manager can add this to their user profile:
programs.z-lua.enable = true;programs.z-lua.enableBashIntegration = true;programs.z-lua.options = [ "enhanced" "once" "fzf" ]; # modify as neededNOTE: For wsl-1 users,
lua-filesystemmust be installed:sudo apt-get install lua-filesystemTo avoid a wsl-1defect.
Zsh:
put something like this in your
.zshrc:eval "$(lua /path/to/z.lua --init zsh)"Options like "enhanced", "once" and "fzf" can be used after
--inittoo. It can also be initialized from "skywind3000/z.lua" with your zsh plugin managers (antigen / oh-my-zsh).NixOS users using home-manager can add this to their user profile:
programs.z-lua.enable = true;programs.z-lua.enableZshIntegration = true;programs.z-lua.options = [ "enhanced" "once" "fzf" ]; # modify as neededNOTE: for wsl-1 users,
lua-filesystemmust be installed.Posix Shells:
put something like this in your
.profile:eval "$(lua /path/to/z.lua --init posix)"For old shells like ksh (Korn Shell), some features are missing, you can try:
eval "$(lua /path/to/z.lua --init posix legacy)"To generate old posix compatible script.
Fish Shell (version
2.4.0or above):Create
~/.config/fish/conf.d/z.fishwith following codelua /path/to/z.lua --init fish | sourceIf you'd like
z.luato cooperate with fish's owndirectory history, you can putset -gx _ZL_CD cdinto the same file.
NixOS users using home-manager can add this to their user profile:
programs.z-lua.enable = true;programs.z-lua.enableFishIntegration = true;programs.z-lua.options = [ "enhanced" "once" "fzf" ]; # modify as neededNushell
Put something like this in your
env.nu:lua /path/to/z.lua --init nushell | save -f ~/.cache/zlua.nuThen put something like this in your
config.nu:source ~/.cache/zlua.nuNote: Only Nushell v0.96+ is supported
Power Shell:
⚠️ WARNING: users ofStarship Prompt should add the following commandafterstarship init.put something like this in your
profile.ps1:Invoke-Expression (& { (lua /path/to/z.lua --init powershell) -join "`n" })Windows cmd (with clink):
- Copy z.lua and z.cmd to clink's home directory
- Add clink's home to
%PATH%(z.cmd can be called anywhere) - Ensure that "lua" can be called in
%PATH%
Windows cmder:
- Copy z.lua and z.cmd to cmder/vendor
- Add cmder/vendor to
%PATH% - Ensure that "lua" can be called in
%PATH%
Windows WSL-1:
Install
lua-filesystemmodule before init z.lua:sudo apt-get install lua-filesystemThis module is required due to a wsl-1defect.
- set
$_ZL_CMDin .bashrc/.zshrc to change the command (default z). - set
$_ZL_DATAin .bashrc/.zshrc to change the datafile (default ~/.zlua). - set
$_ZL_NO_PROMPT_COMMANDif you're handling PROMPT_COMMAND yourself. - set
$_ZL_EXCLUDE_DIRSto a comma separated list of dirs to exclude. - set
$_ZL_ADD_ONCEto '1' to update database only if$PWDchanged. - set
$_ZL_MAXAGEto define a aging threshold (default is 5000). - set
$_ZL_CDto specify your own cd command (default isbuiltin cdin Unix shells). - set
$_ZL_ECHOto 1 to display new directory name after cd. - set
$_ZL_MATCH_MODEto 1 to enable enhanced matching. - set
$_ZL_NO_CHECKto 1 to disable path validation, usez --purgeto clean - set
$_ZL_HYPHENto 0 to treat a hyphen (-) as alua regexp special character,set$_ZL_HYPHENto 1 to treat a hyphen as a normal character.If$_ZL_HYPHENis not set or if it is set toauto, z.lua tries to treat-as a lua regexp special character first. If there are no matches, z.lua triesagain, this time treating-as a normal character. - set
$_ZL_CLINK_PROMPT_PRIORITYchange clink prompt register priority (default 99).
The rank of directories maintained by z.lua undergoes aging based on a simple formula. The rank of each entry is incremented every time it is accessed. When the sum of ranks is over 5000 ($_ZL_MAXAGE), all ranks are multiplied by 0.9. Entries with a rank lower than 1 are forgotten.
Frecency is a portmanteau of 'recent' and 'frequency'. It is a weighted rank that depends on how often and how recently something occurred. As far as I know, Mozilla came up with the term.
To z.lua, a directory that has low ranking but has been accessed recently will quickly have higher rank than a directory accessed frequently a long time ago. Frecency is determined at runtime.
By default,z.lua uses default matching algorithm similar to the originalz.sh. Paths must be match all of the regexes in order.
cd to a directory contains foo:
z foouse multiple arguments:
Assuming the following database:
10 /home/user/work/inbox30 /home/user/mail/inbox"z in"would cd into/home/user/mail/inboxas the higher weighted entry. However you can pass multiple arguments to z.lua to prefer a different entry. In the above example,"z w in"would then change directory to/home/user/work/inbox.use regexes:
z foo$# cd to a directory ends with fooz %d# cd to a directory that contains a digit
Unlike
z.sh,z.luauses theLua regular expression syntax.
Enhanced matching can be enabled by exporting the environment:
export _ZL_MATCH_MODE=1Or, append aenhanced after--init xxx:
eval"$(lua /path/to/z.lua --init bash enhanced)"
For a given set of queries (the set of command-line arguments passed to z.lua), a path is a match if and only if:
- Queries match the path in order (same as default method).
- The last query matches the last segment of the path.
If no match is found, it will fall back to default matching method.
match the last segment of the path:
Assuming the following database:
10 /home/user/workspace20 /home/user/workspace/project130 /home/user/workspace/project240 /home/user/workspace/project3If you use
"z wo"in enhanced matching mode, only the/home/user/workspacewill be matched, because according to rule No.2 it is the only path whose last segment matches"wo".Since the last segment of a path is always easier to be recalled, it is sane to give it higher priority. You can also achieve this by typing
"z space$"in both methods, but"z wo"is easier to type.Tips for rule No.2:
- If you want your last querynot only to match the last segment of the path, append '$' as the last query. eg.
"z wo $". - If you want your last querynot to match the last segment of the path, append '/' as the last query. eg.
"z wo /".
- If you want your last querynot only to match the last segment of the path, append '$' as the last query. eg.
cd to the existent path if there is no match:
Sometimes if you use:
z fooAnd there is no matching result in the database, but there is an existent directory which can be accessed with the name "foo" from current directory, "
z foo" will just work as:cd fooSo, in the enhanced matching method, you can always use
zlikecdto change directory even if the new directory is untracked (hasn't been accessed).Skip the current directory:
When you are calling
z xxxbut the best match is the current directory, z.lua will choose the 2nd best match result for you. Assuming the database:10 /Users/Great_Wall/.rbenv/versions/2.4.1/lib/ruby/gems20 /Library/Ruby/Gems/2.0.0/gemsWhen I use
z gemsby default, it will take me to/Library/Ruby/Gems/2.0.0/gems, but it's not what I want, so I press up arrow and executez gemsagain, it will take me to/Users/Great_Wall/.rbenv/versions/2.4.1/lib/ruby/gemsand this what I want.Of course, I can always use
z env gemsto indicate what I want precisely. Skip the current directory means when you usez xxxyou always want to change directory instead of stay in the same directory and do nothing if current directory is the best match.
The default matching method is designed to be compatible with original z.sh, but the enhanced matching method is much more handy and exclusive to z.lua.
By default, z.lua will add current directory to database each time before display command prompt (correspond with z.sh). But there is an option to allow z.lua add path only if current working directory changed.
To enable this, you can set$_ZL_ADD_ONCE to1 before init z.lua. Or you can initialize z.lua on linux like this:
eval"$(lua /path/to/z.lua --init bash once)"eval"$(lua /path/to/z.lua --init zsh once)"lua /path/to/z.lua --init fish once|source
Withadd once mode off (default), z.lua will consider the time you spent in the directory (like z.sh). When this mode is on, consider the times you accessed the directory (like autojump), and that could be much faster on slow hardware.
When there are multiple matches found, usingz -i will display a list:
$ z -i soft3: 0.25 /home/data/software2: 3.75 /home/skywind/tmp/comma/software1: 21 /home/skywind/software> {CURSOR}And then you can input the number and choose where to go before actual cd. eg. input 3 to cd to/home/data/software. And if you just press ENTER and input nothing, it will just quit and stay where you were.
NOTE: for fish shell, this feature requires fish 2.7.0 or above.
From version 1.1.0, a new option"-I" will allow you to use fzf to select when there are multiple matches.
When we use"z -I vim",12 paths contains keyword "vim" has been matched and ordered by their frecent value, the higher frecent comes with the higher rank. Then without cd to the highest ranked path, z.lua passes all the candidates to fzf.
Now you can input some space separated keywords (no order required) or useCTRL+J/CTRL+K (same asUP/DOWN) to select where you want to go, orESC /CTRL+D/G to give up.
Of course, you can always give more keywords toz command to match your destination precisely."z -I" is similar to"z -i", but use fzf. Both"-i" and"-I" provide you another way for path navigation.
Usually,z -I can be aliased tozf (z + fuzzy finder) for convenience. If there are only one path matched,z -I will jump to it directly, fzf will only be invoked for multiple matches."z -I ." or"zf ." can be used to use fzf select from entire database.
For more information about this, please visitwiki - effective with fzf.
NOTE: For fish shell, this feature requires fish 2.7.0 or above. You can specify fzf executable in$_ZL_FZF environment variable,"fzf" will be called by default.
New option"-b" can quickly go back to a specific parent directory in bash instead of typing "cd ../../.." redundantly.
- (No argument):
cdinto the project root, the project root the nearest parent directory with.git/.hg/.svnin it. - (One argument):
cdinto the closest parent starting with keyword, if not find, go to the parent containing keyword. - (Two arguments): replace the first value with the second one (in the current path).If simple substitution does not work, falls back to fuzzily replacing path components.
Let's start by aliasingz -b tozb:
# go all the way up to the project root (in this case, the one that has .git in it)~/github/lorem/src/public$ zb =>cd~/github/lorem# cd into to the first parent directory named g*~/github/vimium/src/public$ zb g =>cd~/github# goto the site directory quickly~/github/demo/src/org/main/site/utils/file/reader/whatever$ zb si =>cd~/github/demo/src/org/main/site# substitute jekyll with ghost~/github/jekyll/test$ zb jekyll ghost =>cd~/github/ghost/test# same as above, but fuzzy~/github/jekyll/test$ zb jek gh => z~/github/ gh /test =>cd~/github/ghost/test# Assuming that's the most frecent match
Backward jumping can also be used with$_ZL_ECHO option (echo $PWD after cd), which makes it possible to combine them with other tools without actually changing the working directory (eg.ls `zb git`).
Environment variable$_ZL_ROOT_MARKERS is a comma separated list for project root locating, and can be redefined as:
export _ZL_ROOT_MARKERS=".git,.svn,.hg,.root,package.json"
If you wantzb jump back to a parent directory contains a.root orpackage.json in it.
Bonus:zb .. equals tocd ..,zb ... equals tocd ../.. andzb .... equals tocd ../../.., and so on. Finally,zb ..20 equals tocd (..)x20.
Bonus: tryz -b -i andz -b -I and you can alias them tozbi andzbf.
For zsh/fish, completion can be triggered byz foo<tab>. and a list of candidates will display in zsh / fish:
Press<tab> again, you can select your destination in a visualized way.
Bash is not as powerful as zsh/fish, so we introduced fzf-completion for bash, initialize your z.lua and appendfzf keyword after--init:
eval"$(lua /path/to/z.lua --init bash enhanced onceecho fzf)"
If you want use fzf completion in zsh, initalize your z.lua and appendfzf keyword after--init:
eval"$(lua /path/to/z.lua --init zsh enhanced onceecho fzf)"
Then press<tab> afterz xxx:
With the help of fzf, completion in bash is much easier now.
z.lua can cooperate withfz forbetter completion result in both bash and zsh, for more information seeFAQ.
NOTE: To enable this, commandfzf must be found in$PATH before initialization.
z.lua provides a fast way to visit MRU directories without typing any keyword. That isdirstack, which records recently visited paths and can be manipulated byz -,z -- andz -{num}:
# display current dir stack$ z -- 0 /home/skywind/work/match/memory-match 1 /home/skywind/.local/etc 2 /home/skywind/software/vifm-0.9.1 3 /home/skywind/work 4 /home/skywind/work/match# cd to the 2nd directory in the stack$ z -2 =>cd /home/skywind/software/vifm-0.9.1# popup stacktop (cd to previous directory), same as "z -0"$ z - =>cd -
Thedirstack is calculated from z.lua's database, and has no dependency on shells or systems. You will not lost records after re-login, and history can be shared across shells and sessions.
There is another way to access MRU directories interactively by utilizing parameter-I (fzf) and-t (sort by time):
alias zh='z -I -t .'
The new aliaszh (jump to history) is very easy to input:
The first column indicates how many seconds ago you have visited, and the second column is the path name. Withzh, you can type some character to use string matching in fzf, or use<Up>/<Down> (as well asCTRL+j/k) to move the selector (red>) up and down.
At last, press<enter> to accept or<ESC> to give up.
Remember to enable theenhanced matching algorithm, the current working directory can be skipped with it.
To add a:z command to theranger file manager, copy theranger_zlua.py file to~/.config/ranger/plugins/.You can then use:z foo,:z -b foo, etc. from ranger. Use:z -h for help.
To define additional commands (:zb for example) in ranger, you can putalias zb z -b into~/.config/ranger/rc.conf.
Recommended aliases you may find useful:
alias zz='z -c'# restrict matches to subdirs of $PWDalias zi='z -i'# cd with interactive selectionalias zf='z -I'# use fzf to select in multiple matchesalias zb='z -b'# quickly cd to the parent directory
Import data from z.sh:
cat~/.z>>~/.zlua
Import data from autojump:
FN="$HOME/.local/share/autojump/autojump.txt"awk -F'\t''{print $2 "|" $1 "|" 0}'$FN>>~/.zlua
Don't forget to read theFrequently Asked Questions.
The slowest part is adding path to history data file. It will run every time when you press enter (installed in $PROMPT_COMMAND). So I profile it on my NAS:
$time autojump --add /tmpreal 0m0.352suser 0m0.077ssys 0m0.185s$time fasd -A /tmpreal 0m0.618suser 0m0.076ssys 0m0.242s$time _z --add /tmpreal 0m0.194suser 0m0.046ssys 0m0.154s$time _zlua --add /tmpreal 0m0.052suser 0m0.015ssys 0m0.030s
As you see, z.lua is the fastest one and requires less resource.
z.lua is fast enough for most case, the path tracking action will be triggered each time when you change your current directory.
So I still recommend the pure lua script for portability and flexibility, but for someone who really care about10ms or1ms things, this module can help them to gain the ultimate speed.
- czmod: native module to boost
z.lua.
Average performance:
| Name | czmod | z.lua |
|---|---|---|
| Update Time | 1.6ms | 13.2ms |
| Query Time | 1.5ms | 9.8ms |
- 1.8.7 (2020-06-29): use lfs or luajit's cffi if possible.
- 1.8.4 (2020-02-10): fish shell: set
$_ZL_ECHOto global scope. - 1.8.3 (2020-02-09): new:
z -b -iandz -b -Ito jump backwards in interactive mode. - 1.7.4 (2019-12-29): new:
$_ZL_HYPHENto treat hyphen as a normal character, seehere. - 1.7.3 (2019-09-07): uselua-filesystem package if possible when
$_ZL_USE_LFSis1. - 1.7.2 (2019-08-01): Improve bash/zsh shell compatibility by@barlik.
- 1.7.1 (2019-06-07): Fixed:
$_ZL_DATAfailure on Linux sometimes. - 1.7.0 (2019-03-09): Supportranger, fix ReplaceFile issue in luajit (windows).
- 1.6.0 (2019-03-04): optimize with ffi module (luajit builtin module).
- 1.5.11 (2019-03-02): fixed: os.path.isdir doesn't work for symbol link folders.
- 1.5.10 (2019-03-01): Prevent writing file racing.
- 1.5.9 (2019-02-25):
z -bshould not match current directory (close #56). - 1.5.8 (2019-02-21): new
$_ZL_FZF_HEIGHTto control--heightparameter in fzf. - 1.5.7 (2019-02-21): rename
$_ZL_FZF_SORTto$_ZL_INT_SORTit will affect both-iand-I. - 1.5.6 (2019-02-20): set
$_ZL_FZF_SORTto 1 to sort directories by alphabet in fzf. - 1.5.5 (2019-02-20):
$_ZL_FZF_FLAGcan be used to override fzf flags, default to "+s -e". - 1.5.4 (2019-02-19): fixed: file/path existence detection fails on read-only fs (closed#49 by@contrun).
- 1.5.3 (2019-02-17): new
$_ZL_FZF_FLAGfor passing additional flags to fzf, add-eargument to fzf. - 1.5.2 (2019-02-16): be aware of all arguments in fzf completion.
- 1.5.1 (2019-02-15): new: simulated dir stack by
z -,z --andz -{num}. - 1.5.0 (2019-02-14): fixed minor issues in backward jumping.
- 1.4.7 (2019-02-13): Don't use regex in backward jumping (use plain text instead).
- 1.4.6 (2019-02-12): change:
_ZL_EXCLUDE_DIRSto a comma separated list of dirs to exclude. - 1.4.5 (2019-02-10): improve bash fzf completion and posix compatibility.
- 1.4.4 (2019-02-10): supports legacy posix shells like ksh, init with
z.lua --init posix legacy. - 1.4.3 (2019-02-08): fixed minor issues.
- 1.4.2 (2019-02-06): you can disabled path validation by
$_ZL_NO_CHECK, and usez --purgeto clear bad paths manually. - 1.4.1 (2019-02-06): fzf tab-completion in bash (@BarbUk), fixed hang in fish shell (close#29).
- 1.4.0 (2019-02-04): Ported to Power Shell (@manhong2112)
- 1.3.0 (2019-02-04): Backward jumping, prevent "cd ../../.." repeatly.
- 1.2.0 (2019-02-03): Upgrade string lib and path lib.
- 1.1.0 (2019-02-02): New option '-I' to use fzf to select from multiple matches.
- 1.0.0 (2019-02-01): Fixed minor issues and make it stable.
- 0.5.0 (2019-01-21): Ported to Fish Shell (@TeddyDD).
- 0.4.1 (2019-01-20): Don't return failed exit code when $_ZL_ECHO is unbind (Mario Rodas).
- 0.4.0 (2019-01-17): new enhanced matching algorithm,can be enabled by appending
enhancedkeyword after--init. - 0.3.0 (2018-12-26): new option
-ito enable interactive selection. - 0.2.0 (2018-11-25): new option
$_ZL_ADD_ONCEto enable updating datafile only if$PWDchanged. - 0.1.0 (2018-04-30): supports windows cmd, cmder and conemu.
- 0.0.0 (2018-03-21): initial commit, compatible with original z.sh.
This project needs help for the tasks below:
- Support csh/tcsh.
- Completion: Actually I got little knowledge in completion, and need help to improve it.
- Completion: Implement completion for Power Shell.
- Completion: Implement completion for different arguments.
- Packaging: make it possible to be installed easily in different systems or popular plugin managers.
- Thanks to@rupa for inspiring me to start this project.
- Thanks to@vigneshwaranr and@shyiko for inspiring me the backward jumping.
- Thanks to@TeddyDD for Fish Shell porting.
- Thanks to@manhong2112 for Power Shell porting.
- Thanks to@BarbUk for fzf completion in Bash.
- Thanks to@barlik for many improvements.
- Thanks to@brglng for nushell porting.
And many others.
Licensed under MIT license.
About
⚡ A new cd command that helps you navigate faster by learning your habits.
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.



