厌倦了Open With在特定应用程序中右键单击打开文件,我想设置一个快捷方式来在 Gimp 等程序中打开文件。但我不想更改默认打开操作。(Ubuntu 14.04)
我尝试过的:
我已经设置了键盘快捷键来运行下面的脚本,在指定的应用程序(gimp)中打开选定的 Nautilus 文件。
!/bin/sh
for file in $NAUTILUS_SCRIPT_SELECTED_FILE_PATHS
do
/usr/bin/gimp "$file"
done
和...
!/bin/sh
/usr/bin/gimp "$1"
但是,它从未正确地拾取 Nautilus 窗口中选定的文件。
有没有办法做到这一点?
答案1
笔记:此答案中有两种解决方案,每种都有各自的优点。鼓励用户找出最适合其具体情况的解决方案。
介绍
Nautilus 本身不提供定义自定义键盘快捷键及其操作的方法。这是您尝试的脚本失败的主要原因。$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS
只能通过右键单击子菜单使用。但我们可以利用其他东西来实现所需的结果 - 在设置和系统剪贴板中定义的快捷方式。
Nautilus 内置于 Gtk 工具包中。它是一个用于创建图形应用程序的广泛库,除其他功能外,它还具有用于与系统剪贴板交互的实用程序。Nautilus 是一个文件管理器,它的特殊之处在于它会将 URI 列表(格式为file:///home/user/Pictures/encoded%image%name.png
)输出到剪贴板(大多数用户并不了解这一点,而且我已经了解到最近也)。显然,这是 GUI 文件管理器复制文件的方式。
我们可以利用这一事实,复制文件的 URI(或者更确切地说,URI 列表;即使只有一个,它也默认为一个列表)。然后我们可以将该列表传递给gimp
。下面介绍的两个解决方案正是基于这个想法。
2 种解决方案的推理:
我个人认为解决方案 #1 是首选。它依赖于手动按复制快捷键,然后按脚本快捷键 - 这是两个键盘快捷键 - 但它的优势在于依赖性较少。这是一种更手动的方法,但相当不错。它使用os.execlp
call,它将用 Gimp 替换脚本的进程,因此仅充当跳板Gimp
。在脚本和系统编程中,使用exec
函数系列是一种常见的做法
之所以编写第二个解决方案,是因为 Jacob Vlijm 在评论中提到,execlp
无论出于何种原因,该函数对他来说都不起作用。我觉得这很奇怪,因为它execlp
属于os
python 的标准模块,是默认安装的模块之一。此外,subprocess.Popen()
默认为exec()
函数系列;来自subprocess
文档:
在 POSIX 上,shell=False(默认):在这种情况下,Popen 类使用 os.execvp() 来执行子程序。args 通常应为一个序列。字符串将被视为一个序列,其中字符串是唯一的项目(要执行的程序)。
(注:“在 POSIX 上”表示“兼容 POSIX 的操作系统”;Ubuntu 是兼容 POSIX 的)
因此,这似乎不是函数本身的问题,而是用户系统的问题。尽管如此,我还是写了第二个脚本。该脚本使用subprocess
模块并依赖于xdotool
,它将自动为您按下Ctrl+C快捷键,然后启动 Gimp。我个人不太喜欢这个,因为它需要安装额外的项目,但它的优点是只需要一个键盘快捷键。
但想法是一样的。我们仍然使用 Gtk 工具来查询剪贴板内容,并且在每种情况下,脚本都必须绑定到快捷方式。
解决方案 #1,两个快捷方式,最少的依赖项
使用方法:选择文件并先按Ctrl+C复制文件,然后按您分配给该脚本的快捷键。execlp
功能将用 替换脚本的流程gimp
。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from gi.repository import Gtk, Gdk
from os import execlp
from time import sleep
from urllib.parse import unquote
import signal
import threading
import subprocess
uris = None
def autoquit():
global uris
#sleep(0.5)
while not uris:
# allow sufficient time to obtain uris
sleep(2)
pass
Gtk.main_quit()
def get_clipboard_contents():
global uris
clip = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
tr = threading.Thread(target=autoquit)
tr.daemon = True
tr.start()
uris = clip.wait_for_uris()
Gtk.main()
return [unquote(i).replace('file://','')
for i in uris]
def main():
signal.signal(signal.SIGINT,signal.SIG_DFL)
files = get_clipboard_contents()
print(files)
args = ['gimp'] + files
execlp('gimp',*args)
if __name__ == '__main__': main()
解决方案 #2:单一快捷方式,xdotool 依赖
该脚本的使用更简单:在 Nautilus 中选择文件并按键盘快捷键。笔记:您必须xdotool
安装才能使用sudo apt-get install xdotool
。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from gi.repository import Gtk, Gdk
from subprocess import Popen,STDOUT
from time import sleep
from urllib.parse import unquote
import sys
def unquote_uri(*args):
uris = args[-2]
unquoted_args = [ str(unquote(i).replace('file://',''))
for i in uris]
with open('/dev/null','w') as dev_null:
proc = Popen(['gimp',*unquoted_args],stdout=dev_null,stderr=STDOUT)
Gtk.main_quit()
def main():
# NOTE: xdotool is REQUIRED for this to work
Popen(['xdotool','key','Ctrl+c'])
sleep(0.5)
clip = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
clip.request_uris(unquote_uri, None)
Gtk.main()
if __name__ == '__main__': main()
设置快捷方式
在这两种情况下,您都需要将脚本链接到快捷方式。打开系统设置 -> 键盘 -> 快捷方式 -> 自定义。点击按钮+。将文件的完整路径作为命令。例如,/home/User_Name/bin/clipboard_launch.py
将快捷方式指定为合理的值。例如,由于我们要调用 Gimp,因此我将脚本指定为Ctrl+ Super+ G。
答案2
通过快捷方式在特定应用程序中打开选定的文件
受到@Serg(+1)概念的启发,提出了一种不同的实现方法:
剧本
#!/usr/bin/env python3
import subprocess
import pyperclip
subprocess.call(["xdotool", "key", "Control_L+c"])
subprocess.Popen(["gimp", pyperclip.paste()])
如何使用
该脚本需要
pyperclip
和xdotool
(有关xdotool- less
用法,请参阅注释):对于 16.04+:
sudo apt-get install python3-pyperclip xdotool
对于 14.04:
sudo apt-get install python3-pip xdotool sudo pip3 install pyperclip
将脚本复制到一个空文件中,另存为
open_ingimp.py
将其添加到快捷键:选择:系统设置 > “键盘” > “快捷键” > “自定义快捷键”。单击“+”并添加命令:
python3 /path/to/open_ingimp.py
就是这样。现在选择一个有效的文档并按快捷键。该文件将以 格式打开Gimp
。
解释
当按下Ctrl+时C,选择一个文件,该文件的路径将被复制到剪贴板。我们用以下代码模拟:
subprocess.call(["xdotool", "key", "Control_L+c"])
- 事实证明
python
,模块pyperclip
只是生成路径,在file://
使用时被剥离pyperclip.paste()
(这不会真正粘贴,但会使路径在脚本内部可用)。 然后我们需要让脚本做的就是运行命令来打开文件
gimp
。subprocess.Popen(["gimp", pyperclip.paste()])
笔记
如果在按下快捷键在 Gimp 中打开文件之前按下Ctrl+C是可以接受的,我们甚至可以将脚本缩短到几乎一行:
#!/usr/bin/env python3 import subprocess import pyperclip subprocess.Popen(["gimp", pyperclip.paste()])
这将使得安装变得
xdotool
不必要。当然,我们可以稍微修饰/改进一下脚本,使其仅在定义的扩展上运行,或者使应用程序服从参数。只需提及即可。
我们甚至可以设置多个选项:用应用程序 1 打开文件类型 A,用应用程序 2 打开文件类型 B,而无需弄乱打开文件的默认应用程序,或弄乱右键单击选项。