【问题标题】:Quickly find if Java was launched from Windows cmd or Cygwin terminal快速查找 Java 是从 Windows cmd 还是 Cygwin 终端启动的
【发布时间】:2017-04-14 02:59:15
【问题描述】:

我有一个可以在 Windows 命令提示符和 Cygwin 终端中使用的 Java 应用程序。该程序使用和操作文件路径。拥有一个sep 变量非常有用,当程序从 Cygwin 启动时为 /,而当程序从 Windows 启动时为 \\

看着here,我不确定这是否可能,但我想问一下。

我将在几分钟后发布一个可编译的小型应用程序来显示问题。现在,我只想说我想要一组类似的函数:

// in main
...
String sep = getSeparatorToUse();
...

// member functions
...
private boolean wasLaunchedFromWinCmd() 
{
  if (<something-here-that-knows-it-was-cmd-not-cygwin>)
    return true;

  return false;

}//endof:  private boolean wasLaunchedFromWinCmd()

private String getSeparatorToUse()
{
  if (wasLaunchedFromWinCmd)
    return "\\"

  return "/"

}//endof:  private String getSeparatorToUse()

感谢@Raphael_Moita。这些非常有用,我可能会在我将使用的应用程序的 Linux 版本中使用它们。 @Luke_Lee,我没有意识到这一点感到很愚蠢。我想你们两个可能在我准备好可编译代码的时候解决了我的问题。当程序从批处理脚本运行时仍然存在一个问题 - 当它从 find 命令中获取文件名时。我希望我展示的内容能说明这一点。

示例

所有示例都是从 Cygwin 运行的。

Works:大多数志愿者使用代码的方式,只是与 java 代码位于同一目录中的文件名。

$ java FileSeparatorExample pic_4.jpg
Here, something will be done with the file,
C:\Users\bballdave025\Desktop\pic_4.jpg

作品:在文件名/文件路径中使用相对文件路径和空格

$ java FileSeparatorExample pretty\ pictures/pic\ 1.jpg
Here, something will be done with the file,
C:\Users\me\Desktop\pretty pictures/pic 1.jpg

$ java FileSeparatorExample ../pic_5.jpg
Here, something will be done with the file,
C:\Users\me\Desktop\../pic_5.jpg

不起作用。有时,find 命令的输出会附带 Cygwin/UNIX 格式的完整文件路径:

$ java FileSeparatorExample /cygdrive/c/David/example/pic.jpg
The file:
C:\Users\bballdave025\Desktop\/cygdrive/c/David/example/pic.jpg
doesn't exist

可编译代码

我只是从我的原始代码中删减,所以如果它看起来太大,我很抱歉。

/**********************************
 * @file FileSeparatorExample.java
 **********************************/

// Import statements
import java.io.File;
import java.io.IOException; 

public class FileSeparatorExample
{ 
  // Member variables
  private static String sep;


  public static void main(String[] args) 
  {
    ////****** DOESN'T WORK AS DESIRED ******////
    sep = java.io.File.separator;
    ////** I want **////
    // sep = getFileSeparator();

    String imageToLoad = null;
    boolean argumentExists = ( args != null && args.length != 0 );

    if (argumentExists)
    {
      boolean thereIsExactlyOneArgument = ( args.length == 1 );
      if (thereIsExactlyOneArgument)
      {
        imageToLoad = args[0];
      }//endof:  if (thereIsExactlyOneArgument)
      else
      {
        // do some other stuff
      }

    }//endof:  if (argumentExists)

    String filenamePath = getFilenamePath(imageToLoad);
    String filenameFile = getFilenameFile(imageToLoad);

    imageToLoad = filenamePath + sep + filenameFile;

    File f = new File(imageToLoad);
    if (! f.exists())
    {
      System.err.println("The file:");
      System.err.println(imageToLoad);
      System.err.println("doesn\'t exist");  

      System.exit(1);

    }//endof:  if (! f.exists())

    System.out.println("Here, something will be done with the file,");
    System.out.println(imageToLoad);

  }//endof:  main


  // member methods
  /**
   * Separates the filename arg into: full path to directory; bare filename
   */
  private static String[] splitFilename(String imageToLoad)
  {
    String[] fileParts = new String[2];

    int indexOfLastSep = imageToLoad.lastIndexOf(sep);
    boolean fullFilenameHasSeparator = ( indexOfLastSep != -1 );
    if (fullFilenameHasSeparator)
    {
      fileParts[0] = imageToLoad.substring(0, indexOfLastSep);
      fileParts[1] = imageToLoad.substring(indexOfLastSep + 1);

    }//endof:  if (fullFilenameHasSeparator)
    else
    {
      // Use the user's directory as the path
      fileParts[0] = System.getProperty("user.dir");
      fileParts[1] = imageToLoad;

    }//endof:  if/else (fullFilenameHasSeparator)

    return fileParts;

  }//endof:  private static String[] splitFilename(String imageToLoad)

  /**
   * Gives the full path to the file's directory (from the filename arg)                       
   * but not the bare filename
   */
  private static String getFilenamePath(String imageToLoad)
  {
    String[] fileParts = splitFilename(imageToLoad);
    return fileParts[0];

  }//endof:  private static String getFilenamePath(String imageToLoad)


  /**
   * Gives the bare filename (no path information)
   */
  private static String getFilenameFile(String imageToLoad)
  {
    String[] fileParts = splitFilename(imageToLoad);
    return fileParts[1];

  }//endof:  private static String getFilenamePath(String imageToLoad)

}//endof:  public class FileSeparatorExample

【问题讨论】:

  • 在有人问之前,我确实知道cygpath。如果我知道将使用 UNIX 样式的路径输入文件路径,我可以使用:java $(cygpath -wp &lt;file-argument&gt;) 这在我的情况下不起作用。无论如何,这没有任何意义,因为那些将使用 Cygwin 程序的人在将 UNIX 风格的路径转换为 ​​Windows 风格的路径时不会遇到问题。
  • 您可以随时使用/

标签: java windows cygwin command-prompt terminal-emulator


【解决方案1】:

您不需要知道您的 Java 下是哪个 SO。如果您的目标是找到要使用的正确文件分隔符,请调用:

java.io.File.separator;

无论如何...要找出哪个 SO java 正在运行(不确定如何检测到 cygwin),请尝试:

boolean isWindows = System.getProperty("os.name").startsWith("win");

【讨论】:

  • 这些都是很好的建议。当我自己在 Linux 上运行代码时,isWindows 将特别有用。一个问题是 java.io.File.separator; 即使从 Cygwin 终端运行时也会返回 `\`。它并不能完全回答我的问题,这就是为什么我没有选择它作为首选答案的原因,但话又说回来,我还没有完全提出我的问题。非常感谢!
  • 我今天一直在思考这个问题,你说的完全正确;我不需要知道我的 Java 下是哪个操作系统。我可以从文件名参数中去掉/cygwin/c(如果存在/cygwin/c 部分。)唯一的问题是文件名参数来自不同的驱动器——可能是公共的、已安装的驱动器/cygdrive/p。我在原始帖子中没有提到这一点。
  • 不过,我确实想知道我的 Java 是从哪个终端/提示符启动的。
【解决方案2】:

这是我想出的答案,几乎回答了我最初的问题。它尝试根据文件名参数确定 Java 代码的启动器。非常感谢@Raphael_Moita 和@Luke_Lee,他们实际上几乎解决了我的问题。他们的解决方案没有回答原始问题,但这部分是因为我没有完全发布原始问题。正如我所说,this 答案并没有完全回答原始问题。如果有人知道完整的解决方案,请告诉我。

我的解决方案是几种方法。按照他们的立场,它们只适用于我的情况——Windows 上的 Cygwin。 (他们是告诉你Java应用程序的文件名参数是否与从Windowscmd启动一致。)我计划发布一组更便携的方法,即其他操作系统。

我确定有问题。请给我指出来。

// in main
...
sep = java.io.File.separator; // Thanks @Luke_Lee
if (args != null && args.length != 0)
  sep = getSeparatorToUse(args[0]);
...

// member functions
...
private boolean wasLaunchedFromWinCmd(String firstArg)
{
  boolean isWindows = System.getProperty("os.name").startsWith("win");
  if (! isWindows)  return false; // Thanks @Raphael_Moita
  else
  {
    String launchDir = System.getProperty("user.dir");
    String rootOfLaunchDir = getRoot(launchDir);
                  // This will come back with something like "C:\" or "P:\"

    String rootOfArgument = getRoot(firstArg);

    if (rootOfArgument.equals("/"))
    {
      String cygwinBase = "/cygdrive/";

      char letterOfRoot = rootOfLaunchDir.charAt(0);
                  // For, e.g., "/Users/me/Desktop/pic_314.jpg"

      if (firstArg.startsWith(cygwinBase))
      {
        int charsToCut = cygwinBase.length();
        letterOfRoot = firstArg.substring(charsToCut, 
                                          charsToCut + 1);

      }//endof:  if (firstArg.startsWith(cygwinBase))

      System.out.println("The root directory of your argument will be:");
      System.out.println(Character.toUpperCase(letterOfRoot) + ":\\");
      System.out.println("In Cygwin, that will be:");
      System.out.println(cygwinBase + 
                         Character.toLowerCase(letterOfRoot) + "/");

      return false;
        // Not always correct, e.g. if someone in Cygwin uses
        // $ java FileSeparatorExample "C:\pic_137.jpg"

    }//endof:  if (rootOfArgument.equals("/"))

    return true;

  }//endof:  if/else (! isWindows)

}//endof:  private boolean wasLaunchedFromCmd()


private String getRoot(String fileOrDir)
{
  File file = new File(fileOrDir).getAbsoluteFile();
  File root = file.getParentFile();
  while (root.getParentFile() != null)
    root = root.getParentFile();

  return root.toString();

}//endof:  private String getRoot();


private String getSeparatorToUse(String firstArg)
{
  if (wasLaunchedFromWinCmd(firstArg))
    return "\\"

  return "/"

}//endof:  private String getSeparatorToUse(String firstArg)

这个解决方案的一部分归功于@Raphael_Moita 和@Luke_Lee,但我还需要参考this SO post。最后一个有助于解决我的具体情况,即文件并非全部托管在 C:\ 驱动器上。

注意 我不会接受我的正确解决方案,因为它没有回答我最初的问题。我希望它可以帮助某人回答原始问题。

【讨论】:

    猜你喜欢
    • 2015-08-13
    • 1970-01-01
    • 2016-03-04
    • 1970-01-01
    • 2015-05-09
    • 2010-10-21
    • 2020-08-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多