问题来源
有时候,我们调用Shell命令来完成一些操作会方便点。比如复制文件调用cp 'src' 'dest'
命令。但是如果源路径或者目标路径中包含一些Linux Shell 中的一些特殊字符时,可能命令执行的结果并不是我们想要的。此时我们就需要对这些命令进行转义。
Shell中的文件操作
# 复制文件
cp 'src' 'dest'
# 移动文件
mv 'src' 'dest'
# 创建文件
touch 'fileName'
# 创建文件夹
mkdir 'dirName'
如何处理路径特使字符
Shell特殊字符
- shell通配符(wildcard)
*,? [] ,{}
- shell元字符(特殊字符 Meta)
| & ; ( ) < > space tab
|| & && ; ;; ( ) | <newline>
- shell转义符
'
,"
,\
转义特殊字符的三种方式
- 单引号
''
(硬转义)
其内部所有的shell 元字符、通配符都会被关掉。注意,硬转义中不允许出现'
(单引号)。 - 双引号
""
(软转义)
其内部只允许出现特定的shell 元字符:$
用于参数代换'
用于命令代替 - 转义
\
(转义)
去除其后紧跟的元字符或通配符的特殊意义。
怎么选择处理方式
之前我不想匹配那么多特殊字符,使用的是单引号的方式来处理路径中的特殊字符,直到有用户反馈操作一直等待。检查半天发现是他的文件名中有单引号'
,导致Shell一直在等待下一个'
输入。所以呢,单引号是不靠谱的,现在是采用第三种方式。
所以:
- 如果确认路径不包含特殊字符,可以不转义
- 如果确认路径不包含单引号
'
,可以硬转义 - 如果都保证不来,就使用单个字符转义
单个字符全转义的Java实现
/**
* 将包含特殊Shell字符的字符串 转换成Shell可执行的字符串
*
* @author yawei
* zyawei@live.com
* @date 18-6-26
* @see <a href="https://www.cnblogs.com/chengmo/archive/2010/10/17/1853344.html">Linux Shell 特殊字符</a>
*/
public class ShellCommandConversionUtils {
private static final char[] SPECIAL_CHARS = new char[]{
'*', '?', '[', ']', '{', '}', ' ', 0x0D, '=', '>', '<', '|', '&', '(',