ranger (简体中文)

From ArchWiki
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
翻译状态:本文是 Ranger翻译。上次翻译日期:2019-10-29。如果英文版本有所更改,则您可以帮助同步翻译。

ranger 是一个基于文本的文件管理器,以 Python 编写。不同层级的目录分别在一个面板的三列中进行展示. 可以通过快捷键, 书签, 鼠标以及历史命令在它们之间移动. 当选中文件或目录时, 会自动显示文件或目录的内容.

主要特性有: vi 风格的快捷键, 书签, 选择, 标签, 选项卡, 命令历史, 创建符号链接的能力, 多种终端模式, 以及任务视图. ranger 可以定制命令和快捷键,包括绑定到外部脚本。最接近的竞争者是 Vifm, 它有 2 个面板以及 vi 风格的快捷键,但是总体特性相对较少。

安装

安装 ranger 包,或其开发版 ranger-gitAUR

用法

终端 里执行 ranger 来启动 ranger.

快捷键 命令
? 打开帮助手册或列出快捷键、命令以及设置项
l, Enter 打开文件
j, k 选择当前目录中的文件
h, l 在目录树中上移和下移
q 退出

定制

第一次启动 ranger 会创建一个目录 ~/.config/ranger/。可以使用以下命令复制默认配置文件到这个目录:

$ ranger --copy-config=all

了解一些基本的 python 知识可能对定制 ranger 会有帮助。

  • rc.conf - 选项设置和快捷键
  • commands.py - 能通过 : 执行的命令
  • rifle.conf - 指定不同类型的文件的默认打开程序。
  • scope.sh - 文件预览相关配置

rc.conf 只需要包含与默认配置文件不同的部分, 因为它们都会被加载。对于 commands.py,如果你没有包含整个文件,把下面这一行加入到文件起始处:

from ranger.api.commands import *

更多配置选项请参考 ranger(1)

移动到回收站

如果想添加一个把文件移动到目录 ~/.local/share/Trash/files/ 的快捷键 DD, 把以下这一行添加到 ~/.config/ranger/rc.conf:

map DD shell mv %s /home/${USER}/.local/share/Trash/files/

或使用 glib2 软件包提供的 GIO 命令:

map DD shell gio trash %s

一般的图形文件管理器都支持查看或清空回收站,此外还可以使用 gio list trash:// 命令查看,用 gio trash --empty 命令清空回收站。

命令定义

继续上面的例子,在 ~/.config/ranger/commands.py 增加如下代码将会定义一个清空垃圾箱 ~/.Trash 的命令。

class empty(Command):
    """:empty

    Empties the trash directory ~/.Trash
    """

    def execute(self):
        self.fm.run("rm -rf /home/myname/.Trash/{*,.[^.]*}")

输入 :emptyEnter 来执行命令, 如果希望的话,也可以使用 tab 补全。

警告: 注意 [^.] 是上面命令的必要部分。否则,它会删除所有 ..* 形式的文件和目录,即删除你家目录的所有数据。
提示: 你可以在官方 wiki 中找到很多有用的命令。

配色方案

Ranger 配备了四个配色方案:默认丛林积雪烈日。 下列命令可自定义配色:

 set colorscheme scheme

自定义配色方案放在 ~/.config/ranger/colorschemes

文件关联

Ranger 使用自己的文件打开程序,名为rifle,它的配置文件为 ~/.config/ranger/rifle.conf。如果该文件不存在,可运行 ranger --copy-config=rifle 生成。例如,如下的代码指定 kile 为打开 tex 文件的默认程序。

ext tex = kile "$@"

使用 xdg-utils 来打开所有文件,设置 $EDITOR$PAGER:

else = xdg-open "$1"
label editor = "$EDITOR" -- "$@"
label pager  = "$PAGER" -- "$@"

提示与技巧

Tango-edit-clear.pngThis article or section needs language, wiki syntax or style improvements. See Help:Style for reference.Tango-edit-clear.png

Reason: (Discuss in Talk:Ranger (简体中文))

存档相关

可以使用 atoolp7zip 来进行存档操作。

解压缩

下面的命令实现了复制(yy)一个或多个存档文件,然后执行 ":extracthere" 解压到需要的目录。

import os
from ranger.core.loader import CommandLoader

class extracthere(Command):
    def execute(self):
        """ Extract copied files to current directory """
        copied_files = tuple(self.fm.copy_buffer)

        if not copied_files:
            return

        def refresh(_):
            cwd = self.fm.get_directory(original_path)
            cwd.load_content()

        one_file = copied_files[0]
        cwd = self.fm.thisdir
        original_path = cwd.path
        au_flags = ['-X', cwd.path]
        au_flags += self.line.split()[1:]
        au_flags += ['-e']

        self.fm.copy_buffer.clear()
        self.fm.cut_buffer = False
        if len(copied_files) == 1:
            descr = "extracting: " + os.path.basename(one_file.path)
        else:
            descr = "extracting files from: " + os.path.basename(one_file.dirname)
        obj = CommandLoader(args=['aunpack'] + au_flags \
                + [f.path for f in copied_files], descr=descr)

        obj.signal_bind('after', refresh)
        self.fm.loader.add(obj)

对于使用 7z 的用户, 可以在添加以下命令后, 选中压缩包然后执行 ":extract" 或通过绑定的快捷键来解压

class extract(Command):
    """:extract <paths>
    
    Extract archives using 7z
    """
    def execute(self):
        import os
        fail=[]
        for i in self.fm.thistab.get_selection():
            ExtractProg='7z x'
            if i.path.endswith('.zip'):
                # zip encoding issue
                ExtractProg='unzip -O gbk'
            elif i.path.endswith('.tar.gz'):
                ExtractProg='tar xvf'
            elif i.path.endswith('.tar.xz'):
                ExtractProg='tar xJvf'
            elif i.path.endswith('.tar.bz2'):
                ExtractProg='tar xjvf'
            if os.system('{0} "{1}"'.format(ExtractProg, i.path)):
                fail.append(i.path)
        if len(fail) > 0:
            self.fm.notify("Fail to extract: {0}".format(' '.join(fail)), duration=10, bad=True)
        self.fm.redraw_window()

PS: 如果需要解压 ZIP 压缩包还需要安装 unzip-iconvAUR[损坏的链接:package not found](为了解决中文乱码问题)

压缩

以下命令允许用户将当前目录下选中的文件通过":compress <package name>"命令压缩。它还支持通过当前目录名和为扩展名追加几种可能性来建议名称。

import os
from ranger.core.loader import CommandLoader

class compress(Command):
    def execute(self):
        """ Compress marked files to current directory """
        cwd = self.fm.thisdir
        marked_files = cwd.get_selection()

        if not marked_files:
            return

        def refresh(_):
            cwd = self.fm.get_directory(original_path)
            cwd.load_content()

        original_path = cwd.path
        parts = self.line.split()
        au_flags = parts[1:]

        descr = "compressing files in: " + os.path.basename(parts[1])
        obj = CommandLoader(args=['apack'] + au_flags + \
                [os.path.relpath(f.path, cwd.path) for f in marked_files], descr=descr)

        obj.signal_bind('after', refresh)
        self.fm.loader.add(obj)

    def tab(self):
        """ Complete with current folder name """

        extension = ['.zip', '.tar.gz', '.rar', '.7z']
        return ['compress ' + os.path.basename(self.fm.thisdir.path) + ext for ext in extension]

外部驱动

外部驱动可以通过 udev 或 [udisks] 自动挂载。挂载在 /media 下的驱动可以通过快捷键 gm (go, media) 访问。

镜像挂载

以下命令假设你正在使用 CDemu 作为你的镜像挂载器和一些挂载虚拟驱动器到指定位置 (如 '/media/virtualrom') ,类似于 autofs的系统。不要忘记根据你的系统设置修改挂载路径.

为了从 ranger 里把镜像挂载到 cdemud 虚拟驱动器, 需要选中镜像文件然后在终端输入 ':mount'。根据你的设置,挂载可能会需要一些时间(我的需要长达一分钟的时间). 以下命令使用自定义的 loader 会等待加载过程结束然后通过后台在第 9 标签打开挂载了的镜像.

import os, time
from ranger.core.loader import Loadable
from ranger.ext.signals import SignalDispatcher
from ranger.ext.shell_escape import *

class MountLoader(Loadable, SignalDispatcher):
    """
    Wait until a directory is mounted
    """
    def __init__(self, path):
        SignalDispatcher.__init__(self)
        descr = "Waiting for dir '" + path + "' to be mounted"
        Loadable.__init__(self, self.generate(), descr)
        self.path = path

    def generate(self):
        available = False
        while not available:
            try:
                if os.path.ismount(self.path):
                    available = True
            except:
                pass
            yield
            time.sleep(0.03)
        self.signal_emit('after')

class mount(Command):
    def execute(self):
        selected_files = self.fm.env.cwd.get_selection()

        if not selected_files:
            return

        space = ' '
        self.fm.execute_command("cdemu -b system unload 0")
        self.fm.execute_command("cdemu -b system load 0 " + \
                space.join([shell_escape(f.path) for f in selected_files]))
 
        mountpath = "/media/virtualrom/"

        def mount_finished(path):
            currenttab = self.fm.current_tab
            self.fm.tab_open(9, mountpath)
            self.fm.tab_open(currenttab)

        obj = MountLoader(mountpath)
        obj.signal_bind('after', mount_finished)
        self.fm.loader.add(obj)

PDF文件预览

在默认情况下,ranger将会以文本的形式预览PDF文件。然后,你可以通过先将PDF文件转换为图片,再以图片的方式预览PDF文件。ranger将图片预览保存在 ~/.cache/ranger/目录下。你需要手动创建这个目录,或者在~/.config/ranger/rc.confpreview_images设置为true来让ranger在下一次启动时自动创建这个目录。然而,请注意你并不需要将preview_images一直设置为true来以图片的方式预览PDF文件,只要有 ~/.cache/ranger就可以了。

为了启用这个功能,你可以在/usr/share/doc/ranger/config/scope.sh去掉相应行的注释,或者在你本地文件~/.config/ranger/scope.sh中增加/取消注释这些行。

在当前目录打开新标签

你可能已经注意到有两个快捷键能够以家目录为默认目录创建新的标签 (gnCtrl+n). 不妨重新绑定 Ctrl+n:

rc.conf
map <c-n>  eval fm.tab_new('%d')

Shell tips

目录同步

ranger 提供了一个 shell function /usr/share/doc/ranger/examples/shell_automatic_cd.sh. 执行 ranger-cd 会自动切换到最后一次浏览的目录.

如果你的ranger是从一个终端模拟器启动的(比如$TERMCMD -e ranger, 其中 TERMCMD 是某个X终端), 你将无法使用 ranger-cd. 请创建以下可执行脚本:

ranger-launcher.sh
#!/bin/sh
export RANGERCD=true
$TERMCMD

并在你的shell配置文件追加以下内容:

.shellrc
$RANGERCD && unset RANGERCD && ranger-cd

只在设置了RANGERCD变量的情况下才会启动ranger-cd. 其中unset RANGERCD是必要的, 否则在终端中启动一个subshell将会重新启动ranger.

Start a shell from ranger

With the previous method you can switch to a shell in last browsed path simply by leaving ranger. However you may not want to quit ranger for several reasons (numerous opened tabs, copy in progress, etc.). You can start a shell from ranger (S by default) without losing your ranger session. Unfortunately, the shell will not switch to the current folder automatically. Again, this can be solved with an executable script:

shellcd
#!/bin/sh
export AUTOCD="$(realpath "$1")"

$SHELL

and - as before - add this to at the very end of your shell configuration:

shellrc
cd "$AUTOCD"

Now you can change your shell binding for ranger:

rc.conf
map S shell shellcd %d

Alternatively, you can make use of your shell history file if it has any. For instance, you could do this for zsh:

shellcd
## Prepend argument to zsh dirstack.
BUF="$(realpath "$1")
$(grep -v "$(realpath "$1")" "$ZDIRS")"
echo "$BUF" > "$ZDIRS"

zsh

Change ZDIRS for your dirstack.

避免在 ranger 启动的 shell 内创建新的 ranger

Put this in your shell's startup file:

rg() {
    if [ -z "$RANGER_LEVEL" ]
    then
        ranger
    else
        exit
    fi
}

Execute rg to start or restore ranger.

疑难解答

Artifacts in image preview

无边框边栏可能在图片预览中产生条纹。[1]~/.config/ranger/rc.conf 设置:

set draw_borders true

可以解决这个问题

参见