1

1 Overview

This article mainly describes how to use xsel to access the system clipboard in the Linux environment.

2 Causes

Directly search for " Java access clipboard" in the search engine, most of which are directly used AWT API for access examples:

 Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
StringSelection selection = new StringSelection("test");
clipboard.setContents(selection, selection);

However, one of the biggest problems is that the program needs to be running all the time to access the clipboard, so if there is no other processing logic, you need to add thread sleep code:

 Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
StringSelection selection = new StringSelection("test");
clipboard.setContents(selection, selection);
TimeUnit.HOURS.sleep(1);

In other words, this is only temporarily copied to the clipboard, not permanently, so, is there any other way to access the clipboard after the running program ends?

3 xsel

xsel is a command-line tool to access the clipboard under Linux , similar to xclip , if it is not installed, you can use the package manager to install it. The command to write to the clipboard is as follows:

 echo "test clipboard" | xsel -ib

From this, I thought of trying to use Runtime :

 public static void main(String[] args) throws Exception {
    Runtime runtime = Runtime.getRuntime();
    // 直接执行命令
    Process process = runtime.exec("echo \"111\" | xsel -ib");
    // 等待执行结束
    process.waitFor();
    StringBuilder builder = new StringBuilder();
    // 获取输出
    BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
    for (String s; ((s = reader.readLine()) != null); ) {
        builder.append(s);
    }
    System.out.println(builder);
    builder = new StringBuilder();
    // 获取错误输出
    reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
    for (String s; ((s = reader.readLine()) != null); ) {
        builder.append(s);
    }
    System.out.println(builder);
    // 获取返回值
    int exitValue = process.exitValue();
    System.out.println("exitValue is " + exitValue);
    if (exitValue != 0) {
        System.out.println("error");
    }
    process.destroy();
}

The output after running is as follows:

 "111" | xsel -ib
"111" | xsel -ib
exitValue is 0

It can be seen that the output result is abnormal, which is equivalent to becoming an execution

 echo "\"111\" | xsel -ib"

That is, the output strings are all parameters of echo .

4 Create a script file

The reason for the above result is that Process does not directly support the use of the pipe operator, so the method of directly creating a script to run the command is adopted.

step:

  • Create a temporary script file: create using Files.createFile
  • Authorization: 700 permission, that is, the owner's read, write, and execute permissions, use Files.setPosixFilePermissions
  • Write script file: write echo str | xsel -ib to the script file, use Files.writeString
  • Execution: use Process.exec to execute the script file
  • Delete: use Files.delete to delete temporary files

code show as below:

 public static void main(String[] args) throws Exception {
    String fileName = "1.sh";
    Path executeFile = Files.createFile(Path.of(fileName));
    Files.setPosixFilePermissions(executeFile, Set.of(PosixFilePermission.OWNER_WRITE,
            PosixFilePermission.OWNER_EXECUTE, PosixFilePermission.OWNER_READ));
    String clipboardContent = "111";
    Files.writeString(executeFile, "echo " + clipboardContent + " | xsel -ib");
    Runtime runtime = Runtime.getRuntime();
    Process process = runtime.exec("./" + fileName);
    process.waitFor();
    StringBuilder builder = new StringBuilder();
    BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
    for (String s; ((s = reader.readLine()) != null); ) {
        builder.append(s);
    }
    System.out.println(builder);
    builder = new StringBuilder();
    reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
    for (String s; ((s = reader.readLine()) != null); ) {
        builder.append(s);
    }
    System.out.println(builder);
    int exitValue = process.exitValue();
    System.out.println("exitValue is " + exitValue);
    if (exitValue != 0) {
        System.out.println("error");
    }
    Files.delete(executeFile);
    process.destroy();
}

output:

 exitValue is 0

There are two blank lines that are newline output of System.out.println() 6d9a26f235b46a061d6a486e98d0ffaf---, indicating that Process f7e919987b11f463d3f3fd29ec7f5f86--- has no content in inputStream and errorStream .

The test results are also normal, and the 111 string can be clipped.

5 Read from clipboard

The principle of reading from the clipboard is similar, that is, the parameters of xsel are different, so I won't expand it here, and put the complete code:

 import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.PosixFilePermission;
import java.util.Set;

public class Main {
    private static final String FILENAME = "1.sh";

    public static void main(String[] args) throws Exception {
        writeToClipboard("111111");
        System.out.println(readFromClipboard());
        writeToClipboard("22222");
        System.out.println(readFromClipboard());
    }

    //写入到剪贴板
    private static void writeToClipboard(String content) throws Exception {
        Path executeFile = createFile("echo " + content + " | xsel -ib");
        exec(executeFile);
    }

    //从剪贴板读取
    private static String readFromClipboard() throws Exception {
        Path executeFile = createFile("xsel -ob");
        return exec(executeFile);
    }

    private static Path createFile(String fileContent) throws Exception {
        Path executeFile = Files.createFile(Path.of(FILENAME));
        Files.setPosixFilePermissions(executeFile, Set.of(PosixFilePermission.OWNER_WRITE,
                PosixFilePermission.OWNER_EXECUTE, PosixFilePermission.OWNER_READ));
        Files.writeString(executeFile, fileContent);
        return executeFile;
    }

    private static String exec(Path executeFile) throws Exception {
        Runtime runtime = Runtime.getRuntime();
        Process process = runtime.exec("./" + FILENAME);
        process.waitFor();
        StringBuilder builder = new StringBuilder();
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        for (String s; ((s = reader.readLine()) != null); ) {
            builder.append(s);
        }
        String res = "";
        if (builder.length() != 0) {
            res = builder.toString();
        }
        reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
        builder = new StringBuilder();
        for (String s; ((s = reader.readLine()) != null); ) {
            builder.append(s);
        }
        if (builder.length() != 0) {
            System.out.println(builder);
        }
        int exitValue = process.exitValue();
        System.out.println("exitValue is " + exitValue);
        if (exitValue != 0) {
            System.out.println("error");
        }
        Files.delete(executeFile);
        process.destroy();
        return res;
    }
}

氷泠
420 声望647 粉丝