对要用作shell参数的String进行编码

时间:2011-03-03 22:10:16

标签: java shell escaping

我需要在linux shell命令中使用文件名作为参数。问题是,java给了我这个名字,保存了所有空格和其他字符,因此shell抱怨。有没有一种方法可以在将字符串传递给shell之前转义所有有问题的字符?

5 个答案:

答案 0 :(得分:9)

有同样的问题,单引号不够(正如罗伯特已经指出的那样)

解决方案:

import com.google.common.escape.Escaper;
import com.google.common.escape.Escapers;

public class YourFancyClass {
    public static final Escaper SHELL_ESCAPE;
    static {
        final Escapers.Builder builder = Escapers.builder();
        builder.addEscape('\'', "'\"'\"'");
        SHELL_ESCAPE = builder.build();
    }
}

为什么这么复杂的替代? That's why.

用例:

System.out.format("ln -f '%s' '%s'%n", 
    SHELL_ESCAPE.escape(anyOrig.toString()),
    SHELL_ESCAPE.escape(duplicate.toString()));

按预期工作:

ln -f '/home/user/Musik/mix-2012-13/aesthesys~ I Am Free, That Is Why I'"'"'m Lost..mp3' '/home/user/Musik/youtube converted/aesthesys~ I Am Free, That Is Why I'"'"'m Lost..mp3'

答案 1 :(得分:3)

如何使用Apache Commons中的Exec模块?它包括一个命令行构建器。另请注意,如果从用户输入中检索文件名,则应该非常小心地将用户输入作为程序参数执行命令。不正确地转义可能会导致执行其他命令(除非我猜测使用了commons模块)。

答案 2 :(得分:1)

在文件名周围添加单引号或双引号通常就足够了,具体取决于名称中可能没有的字符。

答案 3 :(得分:0)

/**
 * According to the syntax of the shell command, the string is escaped by 
 * enclosing it with single quote.
 * 
 * eg. 11'22 ==> '11'\''22'
 *
 * @param addQuote add outer quote or not
 */
public static String escapeShellSingleQuoteString(String s, boolean addOuterQuote) {
    String replace = s.replace("'", "'\\''");
    return addOuterQuote ?  "'" + replace + "'" : replace;
}

/**
 * According to the syntax of the shell command, the string is escaped by
 * enclosing it with double quote.
 * 
 * eg. 11\22"33$44`55 ==> "11\\22\"33\$44\`55"
 *
 * @param addQuote add outer quote or not
 */
public static String escapeShellDoubleQuoteString(String s, boolean addOuterQuote) {
    final List<String> targets = Arrays.asList("\"", "$", "`");
    String escape = escape(s, "\\", targets);
    return addOuterQuote ? '"' + escape + '"' : escape;
}

private static String escape(String s, String escaper, List<String> targets) {
    s = s.replace(escaper, escaper + escaper);
    for (String t : targets) {
        s = s.replace(t, escaper + t);
    }
    return s;
}

答案 4 :(得分:-6)

你应该能够在参数周围放置单引号,并避免完全转义它。这对你有用吗?

旧:myapp -f / bad / path / to / file

新:myapp -f'/ good / path / to / file'