Giter Club home page Giter Club logo

cd's Introduction

cd, but better

A replacement for the default bash/zsh cd command. It can mount FUSE filesystems on-demand, jump down multiple levels of directories, etc. cd always prefers real directories to special commands; so if you had a directory called foo:, cd foo: would just cd into foo:, not try to mount foo: with sshfs.

$ cd machine-name:[path]    # automounts machine-name:path with sshfs
$ cd /dev/sdb1              # create a mountpoint, then sudo-mount it
$ cd **x                    # cd's to the first descendant dir matching /x/
$ cd ..5                    # cd's up five directories
$ cd ..foo                  # cd's up to the nearest dir matching /foo/
$ cd x.tar                  # mounts x.tar with archivemount
$ cd y.zip                  # mounts y.zip with archivemount
$ cd hdfs://namenode:9000   # mounts namenode with hadoop-fuse-dfs
$ cd ^                      # history: go back one directory
$ cd ^^                     # history: go back two directories
$ cd ^10                    # history: go back ten directories
$ cd -10                    # history: go back ten directories
$ cd ^foo                   # history: go back to last dir matching /foo/
$ cd nfs:machine:/woot      # mounts NFS directories
$ cd enc:/path/to/encrypted # mounts an encfs directory
$ cd loop:image.iso         # mounts a loopback image
$ cd au:/usr:/var           # AUFS union mount
$ cd s3://bucket            # s3fs (note that subpaths don't work yet)

# deprecated commands:
$ cd git:/path/to/repo      # mounts git commits as directories (requires YaGFS)

cd git: is now deprecated in favor of ni's git support, which is far more complete and portable.

Fuse and root-mounted directories are unmounted automatically when you cd out of them.

cd also supports symlinks to virtual directories. For example:

$ ln -s machine-name:/foo/bar my-symlink
$ cd my-symlink             # same as cd machine-name:/foo/bar

If you want cd to virtualize the destination of a symlink, the symlink must not point to a real directory.

Using with zsh

cd works just fine with zsh, but you'll need to make sure of a few things. First, make sure KSH_ARRAYS is unset when you load the script; otherwise cd will be in bash-compatible mode and will break under zsh. Second, cd will set BASH_REMATCH and assumes that you'll leave it set (sorry). So if you unset it, cd will start having problems.

Also, cd will nuke any existing zsh_exit you have defined. If you care about this, ping me and I'll make it non-clobbering.

Interactive options

$ cd --history              # prints $PWD history, most recent first
$ cd --mounts               # lists probably-active FUSE mount points
$ cd --patterns             # all patterns that 'cd' is looking for
$ cd --clean                # attempts to unmount and remove all mounts
$ cd --which enc:x          # indicates which delegate is used for enc:x

The --clean option is good for cases where FUSE mountpoints are left in an inconsistent state; for instance, when you suspend a machine with an open SSHFS connection. It will unmount and remove all mountpoints that aren't in use.

Setup

To enable it (this can also be done from .bashrc):

$ CD_EXTENSIONS=all
$ . cd

Alternatively:

$ CD_EXTENSIONS=(traverse history ssh s3fs archive hdfs encfs dev loop)
$ . cd

Alternatively:

$ . cd                      # enables extensible cd
$ . cd-traverse             # enables descendant/ancestor traversal
$ . cd-history              # ^, ^^, ^n, -n, ^regexp
$ . cd-ssh                  # does nothing unless you have sshfs
$ . cd-s3fs                 # does nothing unless you have s3fs
$ . cd-archive              # does nothing unless you have archivemount
$ . cd-hdfs                 # does nothing unless you have hadoop-fuse-dfs
$ . cd-nfs                  # does nothing unless you have mount.nfs
$ . cd-encfs                # does nothing unless you have encfs
$ . cd-dev                  # enables automounting for /dev/ entries
$ . cd-loop                 # enables mounting for loopback files
$ . cd-missing-mkdir        # mkdir -p if you cd someplace nonexistent

You can see the patterns that are handled by running cd --patterns. (This can be useful if you want to find out which ones are ignored due to unmet dependencies.) Anything that isn't a pattern is treated like a regular directory change.

Be sure to initialize this script after RVM. RVM redefines cd, clobbering any existing redefinitions. This script, on the other hand, preserves RVM's cd redefinition while adding behavior of its own.

Some of cd's extensions store state and/or create temporary mountpoints in ~/.cd, which it automatically creates.

mkdir functionality

$ . cd-missing-mkdir

Sourcing this script causes cd to create directories that don't exist. Any leaf directory created by cd will be removed upon leaving if it is empty and no process is using it. So, for example:

$ ls
foo  bar
$ cd BOOYAH
$ cd ..
$ ls
foo  bar
$

At this point cd will create but not delete parent directories:

$ ls
foo  bar
$ cd bif/baz/bok
$ cd ../../..
$ ls
foo  bar  bif
$ ls bif
baz
$ ls bif/baz
$

Authors

License

MIT as always.

cd's People

Contributors

spencertipping avatar stfactual avatar vivien avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cd's Issues

Issues with traverse

  • cd ..foo goes to /:
vivien@trivette / $ cd ~/projects/cd
vivien@trivette cd $ cd ..projects
vivien@trivette / $
  • cd **foo doesn't seem to work from level 3:
vivien@trivette tmp $ mkdir -p plop/bar/boo/baz
vivien@trivette tmp $ cd **bar
vivien@trivette bar $ cd -
vivien@trivette tmp $ cd **boo
bash: cd: ./**/boo: No such file or directory

handle systems without sudo

Some systems don't have the sudo command, which makes the cd-dev plugin unusable.
I have a WIP root branch which tries to solve that. This commit introduces a cd_as_root() function, which uses either sudo or su -c.

The side-effect is that functions like cd_mount() have to be rewritten to handle the root option. This commit adds a --as-root option to cd_mount(), but I'm not really proud of it. There should be a simpler approach. What do you think?

Cheers,
Vivien

cd_history: bad array subscript

It shows many cd_history: bad array subscript. I tracked the code and found this.

https://github.com/spencertipping/cd/blob/master/cd-history#L39
https://github.com/spencertipping/cd/blob/master/cd#L71

"${cd_history[-1]}" causes the error. I think it is a bug. Could you fix it?


My cd configuration:

CD_EXTENSIONS=(traverse history)

My bash version: GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15)
And current options for bash:

set -o
allexport      	off
braceexpand    	on
emacs          	on
errexit        	off
errtrace       	off
functrace      	on
hashall        	on
histexpand     	off
history        	on
ignoreeof      	on
interactive-comments	on
keyword        	off
monitor        	on
noclobber      	off
noexec         	off
noglob         	off
nolog          	off
notify         	off
nounset        	off
onecmd         	off
physical       	off
pipefail       	on
posix          	off
privileged     	off
verbose        	off
vi             	off
xtrace         	off
shopt
cdable_vars    	off
cdspell        	off
checkhash      	off
checkwinsize   	on
cmdhist        	on
compat31       	off
dotglob        	off
execfail       	off
expand_aliases 	on
extdebug       	on
extglob        	on
extquote       	on
failglob       	off
force_fignore  	on
gnu_errfmt     	off
histappend     	on
histreedit     	on
histverify     	off
hostcomplete   	on
huponexit      	off
interactive_comments	on
lithist        	off
login_shell    	on
mailwarn       	off
no_empty_cmd_completion	off
nocaseglob     	off
nocasematch    	off
nullglob       	off
progcomp       	on
promptvars     	on
restricted_shell	off
shift_verbose  	off
sourcepath     	on
xpg_echo       	off

cd ^n tries to match a regex

According to the doc, cd ^4 should go up 4 directories, but it tries to matches 4 instead:

$ cd ^4
cd: no history matching the regexp '4'

Cheers!

cd .. from a mountpoint goes back in history

Hi, I'm not sure if it is a bug or a feature, but we have this behavior:

vivien@trivette cd $ pwd
/home/vivien/projects/cd
vivien@trivette cd $ cd /dev/sdb
vivien@trivette -dev-sdb $ pwd
/home/vivien/.cd/mountpoints/-dev-sdb
vivien@trivette -dev-sdb $ cd ..
vivien@trivette cd $ pwd
/home/vivien/projects/cd

From a mountpoint, cd .. is equivalent to cd ^ or cd -.

Feature Request: Source All Script

It would be nice if there were a little wrapper script that would source all of the other scripts so that your bashrc (or equivalent) could simply include a line like $ . cd-all.

cd to a non-existent dir in parent dir goes to /

Hi, I spotted this unwanted behavior:

vivien@trivette cd $ pwd
/tmp/cd
vivien@trivette cd $ ls ../src
ls: cannot access ../src: No such file or directory
vivien@trivette cd $ cd ../src
vivien@trivette / $ pwd
/

Sorry, I don't have the time right now to investigate more.

Cheers,
Vivien

Support `cd -5`

This should be an alias for cd ^^5. zsh interprets ^ specially, so it needs to be escaped which is annoying. Also given cd - means go back one dir in regular cd, this seems a more regular syntax extension.

Still not sure if this is genius or insanity btw. ;)

cd-mkdir

Hi Spencer,

A behavior I'd like to have is auto-create target dirs. i.e. something to avoid the following sequence:

$ mkdir -p foo/bar
$ cd !$

Here's a cd-mkdir wrapper I wrote:

#!/bin/bash
# mkdir wrapper | Vivien Didelot
# Licensed under the terms of the MIT source code license

cd_on '^%' cd_mkdir

function cd_mkdir {
  local target="${1#%}"
  mkdir -p "$target"
  cd_goto "$target"
}

So the previous command can now be done with:

$ cd %foo/bar

But I'm not quite happy with a % prefix. I thought about a smarter "implicit-mkdir" feature, which acts as follow:

  1. if the argument to cd is not caught by any wrapper and doesn't exist, call mkdir -p before cd into it;
  2. when cd out of it, remove it if and only if it is empty and not used by any other process. This can be done with: lsof +D "$OLDPWD" >/dev/null || rmdir --ignore-fail-on-non-empty "$OLDPWD"

I didn't think a lot about that, so I might not be aware of any unwanted behavior.
What's your view on such a feature?

Cheers,
Vivien

cd tries to create directories for unknown options

Trying cd -h or cd --help shows that unknown options are passed to mkdir, which may fail. I'm not sure about the behavior we want here.

Supporting cd --help would be nice to document cd --clean and such.

breakage of `cd -`

cd - is a known alias for cd $OLDPWD which is broken with this wrapper:

$ cd -
cd: - does not exist and matches no cd-pattern

non-persistent cd-history

Hi Spencer,

Is there any reason why you prefer a bash array for cd history over the history command?

The bad side is that it is not persistent across different shell instances. I usually abuse the usage of terminals, and would like to do cd ~/projects/foo, open a new term, then cd ^foo.

Relying on history would help if we use history -a before opening a new term.

Otherwise, an option might be to persist the history on disk, for instance in a ~/.cd/history file to which we append / sort -u.

What do you think?

Cheers,
Vivien

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.