批处理 读取剪贴板

批处理 读取剪贴板

批处理 将命令输出写如剪贴板

批处理中如果想把命令的输出写入剪贴板是很容易的,使用管道符+clip即可实现,例如

1
dir | clip

这个命令把dir命令的输出写入到剪贴板中,剪贴板中的文本,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 驱动器 G 中的卷是 原来的C盘
卷的序列号是 0C02-061D

G:\Desktop\Vscode测试 的目录

2019/08/26 23:14 <DIR> .
2019/08/26 23:14 <DIR> ..
2019/07/22 01:44 28 spanButtonCSS.txt
2019/08/26 23:06 146 test.bat
2019/07/23 17:22 314 test.html
2019/07/12 23:33 852 Test.java
2019/05/29 11:18 8,350 test.jsp
2019/07/24 21:19 1,588 test.md
2019/08/26 22:58 57 tmp.txt
2019/08/26 22:24 245 treej.bat
2019/04/29 13:50 613 正则表达式步骤.md
9 个文件 12,193 字节
2 个目录 215,235,579,904 可用字节

cmd中把命令写到剪贴板

clip的输入是前一个命令的输出。如何把命令本身写到剪贴板,而不执行该命令呢。
只需要在前面加上echo命令即可

例如:

1
echo adb install souhushipin.apk | clip

即可把该命令adb install souhushipin.apk复制到剪贴板中。
如果少了echo,

1
adb install souhushipin.apk | clip

则会执行该adb命令,并将该命令的输出写入到剪贴板中。

批处理 读取剪贴板

遗憾的是,批处理好像没有提供读取剪贴板的功能(反正我查了好久没查到).那只能迂回实现了.

for命令可以遍历另一个命令的输出结果

如下格式的for命令,可以遍历单引号中命令的输出结果.注意,命令要写在单引号中.

1
2
3
FOR /F "delims=" %%i in ('命令') do (
echo %%i
)

所以,我只要自己写一个PrintClip命令:这个PrintClip命令可以打印出剪贴板中的文本到标准输出.这样我就可通过上述的for命令遍历PrintClip命令的标准输出,进入实现读取剪贴板的功能。

java代码

这个输出剪贴板文本的代码很简单,如下所示:

PrintClip.java

1
2
3
4
5
6
7
8
9
10
package clipoard.output;
import clipboard.util.SysClipboardUtil;
/**
* 输出剪贴板中的内容.
*/
public class PrintClip {
public static void main(String[] args) {
System.out.print(SysClipboardUtil.getSysClipboardText());
}
}

其中SysClipboardUtil是读写剪贴板的工具类,该工具类源码如下:

SysClipboardUtil.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package clipboard.util;

import java.awt.Image;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.image.BufferedImage;
import java.io.IOException;

public class SysClipboardUtil
{
/**
* 从剪贴板中获取文本.
*
* @return 如果剪贴板中没有文本,则返回null.如果获取到文本,则返回文本.
*/
public static String getSysClipboardText()
{
// 代码兼容JDK6,不然剪贴板获取文本可能错误
System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
String text = null;
Clipboard sysClip = Toolkit.getDefaultToolkit().getSystemClipboard();
// 获取剪切板中的内容
Transferable clipTf = sysClip.getContents(null);

if (clipTf != null)
{
// 检查内容是否是文本类型
if (clipTf.isDataFlavorSupported(DataFlavor.stringFlavor))
{
try
{
// 转换为文本
text = (String) clipTf
.getTransferData(DataFlavor.stringFlavor);
} catch (Exception e)
{
e.printStackTrace();
}
}
}

return text;
}
/**
* 把字符串写到系统剪贴板。
*
* @param writeMe
* 要写入剪贴板的文本
*/
public static void setSysClipboardText(String writeMe)
{
Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable tText = new StringSelection(writeMe);
clip.setContents(tText, null);
}
/**
* 从系统剪贴板获取图片。
*
* @return 系统剪贴板里面的图片。
*/
public static BufferedImage getImageFromClipboard()
{
try
{
Clipboard sysc = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable cc = sysc.getContents(null);
if (cc == null)
return null;
else if (cc.isDataFlavorSupported(DataFlavor.imageFlavor))
return (BufferedImage) cc
.getTransferData(DataFlavor.imageFlavor);
} catch (Exception e)
{
e.printStackTrace();
}
return null;
}

/**
* 把图片复制到剪贴板中。
*
* @param image
* 要复制到剪贴板的图片。
*/
public static void setClipboardImage(final Image image)
{
Transferable trans = new Transferable()
{
public DataFlavor[] getTransferDataFlavors()
{
return new DataFlavor[]
{DataFlavor.imageFlavor};
}

public boolean isDataFlavorSupported(DataFlavor flavor)
{
return DataFlavor.imageFlavor.equals(flavor);
}

public Object getTransferData(DataFlavor flavor)
throws UnsupportedFlavorException, IOException
{
if (isDataFlavorSupported(flavor))
return image;
throw new UnsupportedFlavorException(flavor);
}

};
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(trans,
null);
}

}

PrintClip.java导出成可执行Jar包,然后写一个同名的批处理文件PrintClip.bat来运行这个可执行jar,如下:

1
2
@echo off
java -jar "E:\dev2\idea_workspace\MyJavaTools\runable\PrintClip.jar"

配置path环境变量

为了让PrintClip.bat可以在任意地方调用,需要把PrintClip.bat文件所在的目录的路径配置到**Path环境变量**中,这和把java.exe所在的路径配置到Path环境变量之后,就可也在cmd中执行java命令是一样的道理。
配置好Path环境变量后就可以通过自定义的PrintClip命令来输出剪贴板中的内容了。

测试

现在复制下面的测试字符串:

1
HelloWorld!

然后打开cmd,运行PrintClip命令,效果如下所示:

1
2
3
4
5
6
Microsoft Windows [版本 10.0.17134.915]
(c) 2018 Microsoft Corporation。保留所有权利。

G:\Desktop\Vscode测试>PrintClip
HelloWorld!
G:\Desktop\Vscode测试>

好的现在自定义的命令PrintClip已经可以输出剪贴板中的内容到标准输出了,接下来用for命令遍历PrintClip命令的输出即可读取剪贴板中的内容。

使用For命令读入PrintClip命令的输出

1
2
3
4
5
6
7
8
@echo off
FOR /F "delims=" %%i in ('PrintClip') do (
::保存下剪贴板中的内容
set strInClip=%%i
)
:: 输出剪贴板中的内容
echo 剪贴板中的内容:%strInClip%
pause

现在复制下面的测试字符串:

1
HelloWorld!

然后运行这个批处理,运行效果如下:

1
2
剪贴板中的内容:HelloWorld!
请按任意键继续. . .

好的,这就实现了读取剪贴板的内容了.

应用

我这么做是为了,方便使用自定义的mytree命令打印Java项目的目录结构,这样我在IDE中复制好Java项目的路径之后,就可以通过读取剪贴板中项目的路径,切换盘符,进入项目所在的路径,然后就可以调用mytree命令将项目的目录结构输出到剪贴板中.接着再调用另一个自定义命令m,将剪贴板中的数据格式化成Markdown代码块.
说了一堆,这个批处理代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
@echo off
:: 读取剪贴板中的内容,注意这里要求输入的是Java项目的路径.
FOR /F "delims=" %%i in ('PrintClip') do (
::切换盘符
%%~di
::进入目录
cd %%i
)
:: 打印Java项目的目录结构,并输出重定向到剪贴板中.
mytree java|clip
:: 将剪贴板中的文本封装成Markdown代码块
m cb cmd

其中%%~di是变量拓展,获取该路径所在的盘符的意思,cd %%i表示切换到该路径下.剩下的倒数两个命令是我自定义的命令.