Readit News logoReadit News
modernerd · 12 years ago
I had to modify Jeroen's code to get the `marks` shortcut working under Mac OS 10.8:

    export MARKPATH=$HOME/.marks
    function jump {
        cd -P $MARKPATH/$1 2> /dev/null || echo "No such mark: $1"
    }
    function mark {
        mkdir -p $MARKPATH; ln -s $(pwd) $MARKPATH/$1
    }
    function unmark {
        rm -i $MARKPATH/$1
    }
    function marks {
        ls -l $MARKPATH | sed 's/  / /g' | cut -d' ' -f9- && echo
    }

guygurari · 12 years ago
Here is another version of 'marks' for Mac OS that aligns the arrows. It also works when 'ls' is aliased.

    function marks {
        \ls -l $MARKPATH | tail -n +2 | sed 's/  / /g' | cut -d' ' -f9- | awk -F ' -> ' '{printf "%-10s -> %s\n", $1, $2}'
    }

0x09 · 12 years ago
If you are on a system with BSD stat like OS X you can get the same with

  function marks {
    (cd $MARKPATH && stat -f"%-10SN%SY" *)
  }
Even better with column

  (t="$(printf "\t")"; cd $MARKPATH && stat -f"%N$t%SY" * | column -ts"$t")

flyswatter · 12 years ago
One more fix... if you have group names with spaces this will throw the field number off and you'll see the modification time preceding the mark name.

Adding '-n' to the ls command works around this by causing the group id to be printed instead of the group name and all works, i.e.: \ls -ln "$MARKPATH" | tail -n +2 | sed 's/ / /g' | cut -d' ' -f9- | awk -F ' -> ' '{printf "%-10s -> %s\n", $1, $2}'

beders · 12 years ago
And here's a completion code that works for Mac OS:

  function _jump {
      local cur=${COMP_WORDS[COMP_CWORD]}
      local marks=$(find $MARKPATH -type l | awk -F '/' '{print $NF}')
      COMPREPLY=($(compgen -W '${marks[@]}' -- "$cur"))
      return 0
    }
    complete -o default -o nospace -F _jump jump

cachvico · 12 years ago
Shouldn't this be

  complete -o default -o nospace -F _jump jump unmark
and then it simply replaces the existing _completemarks(), instead of needing both?

svantana · 12 years ago
Thanks! Also, since alot of OSX paths contain whitespaces, I had to modify the mark function like so:

  function mark {
      mkdir -p $MARKPATH; ln -s "$(pwd)" $MARKPATH/$1
    }
Disclaimer: I'm not very good at bash, perhaps there is a nicer solution to this problem?

sambeau · 12 years ago
I went with:

  function marks {
      ls -l $MARKPATH | sed -E 's/ +/ /g' | cut -d' ' -f9- | sed -E 's/ -/     -/g' && echo
  }
where the "\t" (looks like a bunch of spaces in the second sed statement) was typed in using [Ctrl] + [V] and then [Tab].

microcolonel · 12 years ago
I set my version up with a -f on the unmark rm so that I don't need to be prompted to remove it. Also added some basic completion for both jump and unmark

  export MARKPATH=$HOME/.marks
  function jump { 
      cd -P $MARKPATH/$1 2>/dev/null || echo "No such mark: $1"
  }
  function mark { 
      mkdir -p $MARKPATH; ln -s $(pwd) $MARKPATH/$1
  }
  function unmark { 
      rm -if $MARKPATH/$1 
  }
  function marks {
      ls -l $MARKPATH | sed 's/  / /g' | cut -d' ' -f9- | sed 's/ -/\t-/g' && echo
  }

  _completemarks() {
      local curw=${COMP_WORDS[COMP_CWORD]}
      local wordlist=$(find $MARKPATH -type l -printf "%f\n")
      COMPREPLY=($(compgen -W '${wordlist[@]}' -- "$curw"))
      return 0
  }

  complete -F _completemarks jump unmark

coherentpony · 12 years ago
The purpose of the -i flag is to prompt the user before deleting. Mixing the -i and -f flags is a little moot.

Try removing the -i option to obtain what you want.

microcolonel · 12 years ago
Didn't catch that, it was a quick hack of an edit, thanks.
DigitalJack · 12 years ago
I recommend avoiding -f on rm if you can. Make one mistake and it can be painful. In this case think removing the -i from the unmark function will accomplish what you want.

I made something to the OP's system for the same reason of disdain for super deep trees at work. I'll make a gist and edit this post with it in a few minutes.

Edit: https://gist.github.com/desertmonad/6258429

I like the OP's idea of using symbolic links. That makes it more generally useful (i.e. a gui app can use those simple paths too). I may switch over to that.

likeclockwork · 12 years ago
Why not use unlink?
mirkob · 12 years ago
Nice job! I had to modify _completemarks() function though to work on OSX.

  _completemarks() {
    local curw=${COMP_WORDS[COMP_CWORD]}
    local wordlist=$(find $MARKPATH -type l -exec basename {} \;)
    COMPREPLY=($(compgen -W '${wordlist[@]}' -- "$curw"))
    return 0
  }

mcoliver · 12 years ago
nice additions. For OSX I had to modify the local wordlist part of the auto complete function to read:

local wordlist=$(ls $MARKPATH)

Daniel_Newby · 12 years ago
The variable expansions really ought to be quoted, like this:

  function unmark {
      rm -if "$MARKPATH/$1"
  }
Otherwise you are asking for much sadness.

Dead Comment

nkuttler · 12 years ago
To have completion with bash you can use this:

  function _jump {
      local cur=${COMP_WORDS[COMP_CWORD]}
      local marks=$(find $MARKPATH -type l -printf "%f\n")
      COMPREPLY=($(compgen -W '${marks[@]}' -- "$cur"))
      return 0
  }
  complete -o default -o nospace -F _jump jump
Bash completion really needs better docs :-|

christiangenco · 12 years ago
Hmmm, this doesn't seem to work in `zsh`. Typing `jump <tab>` suggests everything in the current directory (folders and files).

Does anyone here know offhand how autocompletion in `zsh` works?

tiziano88 · 12 years ago
nkuttler · 12 years ago
Yeah, I'm a bash user.
Lifescape · 12 years ago
I was in the process of doing this myself and though "I wonder if it's already been posted in the comments". Thank you!
aaren · 12 years ago
I just signed in to post almost exactly this function!
sukaka · 12 years ago
Reminds me of z, which I use all the time. Anyone else use z? If you have not heard of it, get it now https://github.com/rupa/z.

z is a wonderful complement to cd. After cd into a folders with z set up, a file stores all folders navigated to sorted by frecency, then simply jump to a folder with z [foldernameregex].

dmd · 12 years ago
z is absolutely wonderful. Even my boss has become a convert, and he's been hacking unix since the 1970s, when he worked at AT&T, and is very set in his ways.

[Disclaimer: rupa's a good friend of mine]

grimgrin · 12 years ago
I've converted a few people to the z side. And yes, it is wonderful.

[Disclaimer: rupa is a good friend of mine, as well]

skrebbel · 12 years ago
For Windows users I have a closely related shameless plug:

cdhere navigates your cmd.exe to wherever the current topmost Explorer window is pointed at.

It's not the same as the OP's trick, of course, but since you're voluntarily using Windows, I'm going to assume you "live" on the command line less than the average UNIX user, and more on GUI tools such as good old Explorer.

https://github.com/eteeselink/cdhere

Livven · 12 years ago
What many people don't seem to know is that the location bar in Explorer (at least on Windows 8) can act as a run dialog, and it supplies the launched program with the current folder as a parameter. So simply hit Ctrl+L and type "cmd" or "powershell" or whatever command from your PATH and hit enter.
WalterGR · 12 years ago
Amazing tip!

FYI: On Windows 7, you need to press Alt+D to get to the location bar. (I believe that's the case for XP as well.) Ctrl+L doesn't seem to do anything.

TeMPOraL · 12 years ago
Thanks for the tip!

Neither Ctrl+L nor Alt+D work for me (Win7 Ultimate, 64bit), but even with clicking manually this is extremely useful for me.

gizmo686 · 12 years ago
I'm not sure voluntary is necessarily true. I have had to use Windows several times because we were working with Windows only programs.

On a different note, back in UNIX land I found myself doing the opposite of what you described: opening the file explorer to the same directory as the command-line. Of course, there is not much to that trick other than choosing an explorer that opens to the working directory or a path provided as an arguement.

networked · 12 years ago
I like this.

On Windows you can also get a nice "browse for folder" dialog in batch files with Wfolder [1]. If you replace "cdwhere.exe" in your script (cdhere.cmd) with "wfolder.exe" [2] and put wfolder.exe in the same directory as cdhere.cmd then instead of going to the location open in the topmost Explorer window the "cdhere" command will ask you where to cd, starting at your current location (like so: http://i.imgur.com/3MCzD4b.png).

Edit: Wfolder comes with a script that's analogous to cdhere.cmd.

[1] http://www.horstmuc.de/wcon.htm

[2] I did it in http://pastebin.com/aq0FiKmz.

keyboardP · 12 years ago
You can hold shift and right-click in Explorer and select "Open Command Window Here" (at least in Win 7 and 8).
Too · 12 years ago
Or even faster: shift + context menu button, then W.
skrebbel · 12 years ago
Yep, this works fine, until you did it a 7th time and end up with a task bar full of unused console windows.
rntrg · 12 years ago
Another useful windows trick: to open a new file explorer window at the pwd of the command prompt, type 'explorer .'.
recursive · 12 years ago
or slightly shorter: 'start .'
mistercow · 12 years ago
I used to have a really hacky AppleScript to do the same thing in OS X. The crappy part was that launching the whole AppleScript runtime was really slow, but that was the only API I could find with getting that information from the Finder.
mrmaddog · 12 years ago
You can also drag any file or folder onto your terminal, which will paste the absolute filepath at your cursor point.
ams6110 · 12 years ago
You could install cygwin and use the OP technique, though.
tripzilch · 12 years ago
unfortunately cygwin takes a lot longer to start than cmd, so I use it only occasionally. are there any fixes for that maybe? :)
networked · 12 years ago
You can also use ranger [1] to change directories, especially if you want to explore the directory tree quickly when you don't know exactly where to jump to. Install it and add the following to ~/.bashrc:

     function ranger-cd {
       tempfile='/tmp/chosendir'
       /usr/bin/ranger --choosedir="$tempfile" "${@:-$(pwd)}"
       test -f "$tempfile" &&
       if [ "$(cat -- "$tempfile")" != "$(echo -n `pwd`)" ]; then
         cd -- "$(cat "$tempfile")"
       fi
       rm -f -- "$tempfile"
     }

     # This binds Ctrl-O to ranger-cd:
     bind '"\C-o":"ranger-cd\C-m"'
(This script comes from the man page for ranger(1).)

Edit: Modified the above script for use with zsh (and multiple users):

     ranger-cd() {
       tempfile=$(mktemp)
       ranger --choosedir="$tempfile" "${@:-$(pwd)}" < $TTY
       test -f "$tempfile" &&
       if [ "$(cat -- "$tempfile")" != "$(echo -n `pwd`)" ]; then
         cd -- "$(cat "$tempfile")"
       fi
       rm -f -- "$tempfile"
     }

     # This binds Ctrl-O to ranger-cd:
     zle -N ranger-cd
     bindkey '^o' ranger-cd
[1] http://ranger.nongnu.org/.

JoshTriplett · 12 years ago
Good idea, but you shouldn't overwrite ctrl-O, which is a wildly useful function in bash: run current command in history and retrieve the next. If you want to re-run a sequence of several history commands, you can find the first in history (such as via ctrl-R reverse-isearch), then repeatedly hit ctrl-O to run it and retrieve the next command from history.
platz · 12 years ago
Thanks! I was already using ranger and this fits nicely with the i3 ethos as well.
braum · 12 years ago
thanks! I tried: apt-get install ranger

it says it's not available. any idea why ranger is not longer available in package manager?

networked · 12 years ago
What is your distribution? I've just tried it and it's available in both Ubuntu 12.04 and Debian 7. The launchpad page says that it should be in later Ubuntu releases, too. Enable the "universe" repository then run apt-get update and see if it fixes the problem.
rjzzleep · 12 years ago
i'm using fasd a lot but this is absolutely awesome, thank you!
fau · 12 years ago
You might want to check out z: https://github.com/rupa/z
TheEskimo · 12 years ago
https://github.com/clvv/fasd

I used to use z, but I've since switched to fasd. It's much like z, but also so much better. In addition to being able to do "z <part of directory>" you can do "f <part of file>". So, for example, if I've got a rails project I've worked on a lot recently I know its config.ru is high on frecency, so I'll just do "vim `f config`" to edit that file. If I want a file that's not so recent I can always do "vim `f -i config`" to pick from a list of files.

fasd is leaps and bounds above z in functionality, and I've thoroughly enjoyed using it.

wrboyce · 12 years ago
If you alias `v` to `f -e vim` then you can `v config` and `v -i config`.
csharpminor · 12 years ago
Thanks for this. I've been using z and like it quite a bit, but I'm always open to ways to improve my workflow.
kinleyd · 12 years ago
I put z and fasd through their paces, and out of the box z works very intuitively. I like it. fasd takes a little more to get used to, but I'm going to put it through a full try out. Let's see if the additional features make it worth the while. In either case, thanks all for a great thread.
wereHamster · 12 years ago
z is so much more useful because it automatically learns which paths you use most often. There is no need to explicitly mark folders. It just works.
rishigoutam · 12 years ago
How does it differ from autojump?
masnick · 12 years ago
+1 for z. It's the primary way I navigate between folders at the command line.
moonlighter · 12 years ago
Thank you! Glad I read the comments first... seems like z is more powerful yet easier to use. Ended up installing that.
mynameisfiber · 12 years ago
I found this is a useful addition to his scripts... I can't live without my tab completion!

    _jump()
    {
        local cur=${COMP_WORDS[COMP_CWORD]}
        COMPREPLY=( $(compgen -W "$( ls $MARKPATH )" -- $cur) )
    }
    complete -F _jump jump

sgt · 12 years ago
Cleaner than the other variants here that use "find".