59

I am using Ranger terminal file explorer from within a linux terminal.
Say I start from command prompt in home directory and launch ranger

user@/home/user $ ranger

ranger opens..... and within the ranger program I explore to:

/media/ubuntu/sdf675d7sf5sdfs7/some_directory

If I then hit q to quit ranger, I am dropped back to the same folder I launched ranger from. i.e.

user@/home/user $

Is it possible to quit ranger, and remain in the directory I was in with ranger, i.

user@/media/ubuntu/sdf675d7sf5sdfs7/some_directory $  
the_velour_fog
  • 3,529
  • 4
  • 17
  • 20

11 Answers11

53

According to its manual

--choosedir=targetfile    
    Allows you to pick a directory with ranger. When you exit ranger, it will write the last visited directory into targetfile.

So all you need to do is create an alias like this:

alias ranger='ranger --choosedir=$HOME/.rangerdir; LASTDIR=`cat $HOME/.rangerdir`; cd "$LASTDIR"'

And writing this alias into the rc of your favoured shell is recommended.

Mateen Ulhaq
  • 3,452
  • 6
  • 35
  • 56
user556625
  • 4,160
  • 1
  • 17
  • 15
  • 2
    wow thats pretty clever, It never occurred to me you could issue a command to a program, terminate it with a `;` and then specify more commands after the semi-colon which - Im assuming are run at the point you close `ranger` , thanks! – the_velour_fog Feb 22 '16 at 03:25
  • 1
    Consider using `.rangerdir` instead to make it hidden. Or delete it at the end, `rm -d $HOME/rangerdir`. – Mateen Ulhaq Jan 25 '18 at 09:35
  • This is great but it if I understand it correctly, this would mean that you have that behavior permanently. If would be nice if there was a way to have the option to exit into current ranger directory OR the directory you were in when you started ranger. – neverfox Mar 21 '18 at 18:15
  • neverfox Once you create an alias, it's up to you if you offer the selection of the directory to land in inside that alias. The selection can be made before the binary is called or after it's finished. – user556625 Mar 26 '18 at 18:14
  • 2
    Thank you for this awesome solution! I happen to be using the fish shell, so to set my alias, I used `fish_config` and added an abbreviation for `ranger --choosedir="$HOME/.rangerdir"; cd (cat $HOME/.rangerdir)` – rockzombie2 Nov 16 '18 at 05:34
  • @neverfox The way I handled this was simply naming the alias `rangercd`, so that I could either issue the command `ranger` or `rangercd` – Broper Oct 14 '20 at 12:47
49

Shift + S

If you hit Shift + S, it opens a new shell on the current directory.

Then if you hit Ctrl + D on the shell, it goes back to ranger.

This workaround is often good enough.

By the way, I've given up on file managers for a few years now, I just have this in my bashrc instead and I navigate directories simply with tab complete, it's good enough for me:

c() {
  if [ -n "$1" ]; then
    cd "$1" || return 1
  else
    cd ..
  fi
  ll
}
ll() ( ls -hl --time-style="+%Y-%m-%d_%H:%M:%S" "$@"; )

GitHub upstream.

  • You need to hit ` S`, not just `S`. – Atcold Apr 22 '20 at 02:11
  • @Atcold thanks, that's what I meant by the upper case `S`, but clarified now. – Ciro Santilli OurBigBook.com Apr 22 '20 at 06:30
  • Sweet. The keys on a keyboard are *already* capitalised , so if you want to press **two keys** it's fundamental to write it down. – Atcold Apr 22 '20 at 06:34
  • 3
    @Atcold depends. For VIM (which ranger's keybindings are heavily inspired by), it is convention is to write lower case letters if just a key is to be pressed, and uppercase if it is to be pressed with shift. For example, the shortcut for "Go to next occurrence" is `n`, and the shortcut for "Go to previous occurence" is `N`. – iFreilicht Apr 28 '20 at 22:22
33

I found an easier solution. When you install ranger, it will put a script in your bin folder which, if executed, will start the program. But if you source it, with

$ source ranger

it will launch ranger and drop you in the last visited folder when you exit.

so if you want this behavior by default, just do

$ alias ranger='source ranger'

or even better put it into your .bashrc file.

To see the documentation and implementation for this feature, read the ranger script in your bin folder.

Ogino Knaus
  • 431
  • 4
  • 3
  • 15
    Apparently this technique (which can be shortened to just executing `. ranger`) is mentioned in the [wiki](https://github.com/ranger/ranger/wiki/Integration-with-other-programs#changing-directories) – cjauvin Oct 03 '19 at 15:24
  • 1
    This is the way to go! – Merlin Sep 23 '20 at 03:15
5

I stumbled upon a similar question elsewhere with better answer compared to Gambai and its other proposed variants. It is better since.

  1. it will take care of the created file by putting it into the tmp folder so that it can be deleted by the system
  2. it is more clean code (although the Gambai's answer can be converted to a function)

There is a function in a shell file already in ranger's git repo:

https://github.com/ranger/ranger/blob/master/examples/bash_automatic_cd.sh

function ranger-cd {
    # create a temp file and store the name
    tempfile="$(mktemp -t tmp.XXXXXX)"

    # run ranger and ask it to output the last path into the
    # temp file
    ranger --choosedir="$tempfile" "${@:-$(pwd)}"

    # if the temp file exists read and the content of the temp
    # file was not equal to the current path
    test -f "$tempfile" &&
    if [ "$(cat -- "$tempfile")" != "$(echo -n `pwd`)" ]; then
        # change directory to the path in the temp file
        cd -- "$(cat "$tempfile")"
    fi

    # its not super necessary to have this line for deleting
    # the temp file since Linux should handle it on the next
    # boot
    rm -f -- "$tempfile"
}

You can put this function in your favorite's shell rc (for example ~/.zshrc) file and either create alias and/or bind it to a key combination (again both can go in the rc file):

alias nav=ranger-cd

and/or

# This will run the function by Ctrl+O through returning
# the string "ranger-cd" in addition to a new-line character
# to act as Enter key-press
bindkey -s "^o" "ranger-cd\n"

Disclaimer: the bindkey above works in ZSH and you should change it based on your preferred shell

  • You just made my day! This is awesome! I was using `--cmd="map Q chain shell echo` solution but found that it was not using Ranger idiomatic way of the flag `--choosedir`. It was messing with my tmux auto rename function for a long time. Now I found your solution and my tmux problem solved! Thank you with all the inline comments to make it easier to understand and its corporation with zsh! – kohane15 Apr 14 '23 at 15:55
  • If someone wants a python script to do the trick, check out the project [ranger-quit_cd_wd](https://github.com/JohanChane/ranger-quit_cd_wd). – kohane15 Apr 19 '23 at 07:25
  • Leaving here in case someone have the same "redraw" issue as me when using the function: https://github.com/neovim/neovim/issues/24272 – kohane15 Jul 15 '23 at 09:53
4

To piggy back of of Gombai Sándor's answer, i suggest making a minor adjustment to the alias:

alias ranger='ranger --choosedir=$HOME/.rangerdir; LASTDIR=`cat $HOME/.rangerdir`; cd "$LASTDIR"'

By changing "$Home/rangerdir" to "$Home/.rangerdir" you make the file created by the alias hidden. just makes it so it is not annoyingly cluttering up the home folder. it makes no functional difference to how it works.

dduxx
  • 41
  • 1
2

Here's a more elegant way to it by writing a function wrapper. Just use the command ranger, and if you wanna sync directory change back to the main shell, quit ranger with capital Q.

(The codes below is test with Bash and ZSH.)

function ranger {
  local IFS=$'\t\n'
  local tempfile="$(mktemp -t tmp.XXXXXX)"
  local ranger_cmd=(
    command
    ranger
    --cmd="map Q chain shell echo %d > \"$tempfile\"; quitall"
  )

  ${ranger_cmd[@]} "$@"
  if [[ -f "$tempfile" ]] && [[ "$(cat -- "$tempfile")" != "$PWD" ]]; then
    cd -- "$(cat -- "$tempfile")" || return
  fi
  command rm -f -- "$tempfile" 2>/dev/null
}

This will let you sync back the directory change on demand. Use :q to quit normally, Q to quit and change your directory.

kohane15
  • 109
  • 3
Simba
  • 1,178
  • 7
  • 7
1

Thanks for Gombai for the inspiration, but on Ubuntu 14.04 LTS I found the solution didn't quite work. Modifying it slightly and saving as an alias in my .bashrc, the following worked perfectly (after creating the rangerdir file):

alias ranger='ranger --choosedir=$HOME/rangerdir;cd "$(cat $HOME/rangerdir)"'

The following post on askubuntu helped me out when I was trying to figure out why different solutions I was trying weren't working: https://askubuntu.com/questions/404141/why-cant-i-pipe-into-cd

Try431
  • 146
  • 3
1

may i one-up y'all? passing through the other arguments may be useful, so put this in your shellrc

function ranger () {
    /usr/bin/ranger --choosedir=$HOME/.rangerdir $@
    LASTDIR=`cat $HOME/.rangerdir` 
    cd $LASTDIR
    echo -n > $HOME/.rangerdir
}
kohane15
  • 109
  • 3
1

The ranger wiki explains multiple different approaches, depending on your preferences and shell.

The summary is given in the first paragraph:

If you want your shell to remember the directory you've navigated to with ranger, you can run . ranger instead of just ranger, or launch ranger via this function. For the details see #1414. Note that it works only in Bash-compatible shells, i.e. not in Fish.

Karl Bartel
  • 521
  • 4
  • 5
0

You can remap your q by following spinets below in your rc.conf. Next time with you hit q, you will keep the path in the terminal

map q shell $SHELL
SLN
  • 121
  • 6
-1
  1. Create ~/.config/ranger/plugins/quit_cd_wd.py and add the following to the file
import ranger.api
from ranger.api.commands import *
import os

QUIT_CD_WD_FILE = '$HOME/.ranger_quit_cd_wd'

class quit_cd_wd(Command):
    """:chdir to working directory of ranger after quiting on ranger.
    """
    def _exit_no_work(self):
        if self.fm.loader.has_work():
            self.fm.notify('Not quitting: Tasks in progress: Use `quit!` to force quit')
        else:
            self.fm.exit()

    def execute(self):
        if len(self.fm.tabs) >= 2:
            self.fm.tab_close()
        else:
            os.system('echo $PWD > ' + QUIT_CD_WD_FILE)
            self._exit_no_work()

class quitall_cd_wd(Command):
    """:chdir to working directory of ranger after quitalling on ranger.
    """
    def _exit_no_work(self):
        if self.fm.loader.has_work():
            self.fm.notify('Not quitting: Tasks in progress: Use `quitall!` to force quit')
        else:
            self.fm.exit()

    def execute(self):
        os.system('echo $PWD > ' + QUIT_CD_WD_FILE)
        self._exit_no_work()
  1. Add the following mapping to the rc.conf
map     x quit_cd_wd
map     X quitall_cd_wd
  1. Add the following to your shell rcfile (e.g. .bashrc, .zshrc)
function ranger_func {
    ranger $*
    local quit_cd_wd_file="$HOME/.ranger_quit_cd_wd"
    local quit_cd_wd="$(cat $quit_cd_wd_file)"
    if [ -n $quit_cd_wd ]; then
        cd $quit_cd_wd
        true > $quit_cd_wd_file
    fi
}

alias ranger='ranger_func'

Now you can use x, X shortcuts in ranger to quit ranger but keep the working directory.