Batch file 从批处理文件获取命令行参数的短文件名
批处理文件中的以下命令无法按预期/希望的方式工作:Batch file 从批处理文件获取命令行参数的短文件名,batch-file,filenames,command-line-arguments,substitution,Batch File,Filenames,Command Line Arguments,Substitution,批处理文件中的以下命令无法按预期/希望的方式工作: echo%~nxs1 以下是我试图获得的示例显示: C:\>type test.bat @dir /b %1 @echo %~nxs1 C:\>test "C:\Documents and Settings\All Users\ntuser.dat" ntuser.dat NTUSER.DAT C:\>test "C:\Documents and Settings\All Users\ntuser.data" ntuse
echo%~nxs1
以下是我试图获得的示例显示:
C:\>type test.bat
@dir /b %1
@echo %~nxs1
C:\>test "C:\Documents and Settings\All Users\ntuser.dat"
ntuser.dat
NTUSER.DAT
C:\>test "C:\Documents and Settings\All Users\ntuser.data"
ntuser.data
NTUSER~1.DA~
C:\>test "C:\Documents and Settings\All Users\ntuser.dat.baz"
ntuser.dat.baz
NTUSER~1.BAZ
C:\>test "C:\Documents and Settings\All Users\foo.bar.baz"
File Not Found
foo.bar.baz (or FOO~1.BAZ or whatever, doesn’t really matter since
file does not exist, though latter would be nice)
相反,我得到的是如下内容(取决于指定的短文件名):
基本上,我需要将一个文件名传递给一个BAT文件,并让脚本获取(例如显示)它作为一个短文件名,但只包含文件名和扩展名,没有驱动器或路径 例如,for的帮助信息提供了%~fsI,但它将整个路径作为一个短文件名,而不仅仅是文件。有人知道如何组合%~中的S参数而不获得整个路径吗
非常感谢
更新
我在执行批处理时没有问题。希望有人能尽快帮助你。但是,当您使用Vbscript时,这里有一个替代方法,我认为您应该熟悉它
Set objArgs = WScript.Arguments
strFile = objArgs(0)
WScript.Echo CreateObject("Scripting.FileSystemObject").GetFile(strFile).ShortName
在命令行(或批处理)上,按如下方式调用它
C:\test>cscript //nologo getshortname.vbs "C:\Documents and Settings\All Users\Desktop\shortcut.lnk"
shortcut.lnk
还有另一种方法,在VS中编译此代码:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.IO;
using System.Text;
using System.Runtime.InteropServices;
namespace ConvFN
{
class Program
{
static void Main(string[] args)
{
if (args.Length == 3)
{
if ((args[2].Length > 1) && System.IO.File.Exists(args[2]))
{
if (args[1].Equals("-l")) Console.WriteLine(ShortLongFName.GetLongPathName(args[2]));
if (args[1].Equals("-s")) Console.WriteLine(ShortLongFName.ToShortPathName(args[2]));
}
}
}
}
public class ShortLongFName
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern uint GetShortPathName(
[MarshalAs(UnmanagedType.LPTStr)]
string lpszLongPath,
[MarshalAs(UnmanagedType.LPTStr)]
StringBuilder lpszShortPath,
uint cchBuffer);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.U4)]
private static extern int GetLongPathName(
[MarshalAs(UnmanagedType.LPTStr)]
string lpszShortPath,
[MarshalAs(UnmanagedType.LPTStr)]
StringBuilder lpszLongPath,
[MarshalAs(UnmanagedType.U4)]
int cchBuffer);
/// <summary>
/// Converts a short path to a long path.
/// </summary>
/// <param name="shortPath">A path that may contain short path elements (~1).</param>
/// <returns>The long path. Null or empty if the input is null or empty.</returns>
internal static string GetLongPathName(string shortPath)
{
if (String.IsNullOrEmpty(shortPath))
{
return shortPath;
}
StringBuilder builder = new StringBuilder(255);
int result = GetLongPathName(shortPath, builder, builder.Capacity);
if (result > 0 && result < builder.Capacity)
{
return builder.ToString(0, result);
}
else
{
if (result > 0)
{
builder = new StringBuilder(result);
result = GetLongPathName(shortPath, builder, builder.Capacity);
return builder.ToString(0, result);
}
else
{
throw new FileNotFoundException(
string.Format(
CultureInfo.CurrentCulture,
"{0} Not Found",
shortPath),
shortPath);
}
}
}
/// <summary>
/// The ToLongPathNameToShortPathName function retrieves the short path form of a specified long input path
/// </summary>
/// <param name="longName">The long name path</param>
/// <returns>A short name path string</returns>
public static string ToShortPathName(string longName)
{
uint bufferSize = 256;
// don´t allocate stringbuilder here but outside of the function for fast access
StringBuilder shortNameBuffer = new StringBuilder((int)bufferSize);
uint result = GetShortPathName(longName, shortNameBuffer, bufferSize);
return shortNameBuffer.ToString();
}
}
}
使用系统;
使用System.Collections.Generic;
利用制度全球化;
使用System.Linq;
使用System.IO;
使用系统文本;
使用System.Runtime.InteropServices;
名称空间ConvFN
{
班级计划
{
静态void Main(字符串[]参数)
{
如果(args.Length==3)
{
如果((args[2].Length 1)和&System.IO.File.Exists(args[2]))
{
if(args[1].Equals(“-l”))Console.WriteLine(ShortLongFName.GetLongPathName(args[2]);
if(args[1].Equals(“-s”))Console.WriteLine(ShortLongFName.ToShortPathName(args[2]);
}
}
}
}
公共类ShortLongFName
{
[DllImport(“kernel32.dll”,CharSet=CharSet.Auto,SetLastError=true)]
静态外部uint GetShortPathName(
[Marshallas(UnmanagedType.LPTStr)]
字符串lpszLongPath,
[Marshallas(UnmanagedType.LPTStr)]
StringBuilder lpszShortPath,
uint cchBuffer);
[DllImport(“kernel32.dll”,SetLastError=true,CharSet=CharSet.Auto)]
[返回:Marshallas(UnmanagedType.U4)]
私有静态外部int GetLongPathName(
[Marshallas(UnmanagedType.LPTStr)]
字符串lpszShortPath,
[Marshallas(UnmanagedType.LPTStr)]
StringBuilder lpszLongPath,
[Marshallas(UnmanagedType.U4)]
int cchBuffer);
///
///将短路径转换为长路径。
///
///可能包含短路径元素(~1)的路径。
///长路径。如果输入为Null或空,则为Null或空。
内部静态字符串GetLongPathName(字符串短路径)
{
if(String.IsNullOrEmpty(短路径))
{
返回短路径;
}
StringBuilder=新的StringBuilder(255);
int result=GetLongPathName(短路径、生成器、builder.Capacity);
if(结果0&&result builder.Capacity)
{
返回builder.ToString(0,结果);
}
其他的
{
如果(结果0)
{
生成器=新的StringBuilder(结果);
结果=GetLongPathName(短路径、构建器、构建器容量);
返回builder.ToString(0,结果);
}
其他的
{
抛出新的FileNotFoundException(
字符串格式(
CultureInfo.CurrentCulture,
“{0}未找到”,
短路径),
短路径);
}
}
}
///
///ToLongPathNameToSortPathName函数检索指定长输入路径的短路径形式
///
///长名称路径
///短名称路径字符串
公共静态字符串ToSortPathName(字符串longName)
{
uint bufferSize=256;
//不要在此处分配stringbuilder,而是在功能之外,以便快速访问
StringBuilder shortNameBuffer=新的StringBuilder((int)bufferSize);
uint结果=GetShortPathName(longName、shortNameBuffer、bufferSize);
返回shortNameBuffer.ToString();
}
}
}
将其添加到名为ConvFN的控制台C#项目中并构建它。然后从批处理文件中调用ConvFN-s%1,其中%1参数是一个长文件名,它将输出等效的短文件名…与此相反,ConvFN-l%1其中%1是短文件名,它将输出等效的长文件名
这段代码取自pinvoke.net。我刚刚确认过。我使用xpsp1、SP2和SP3中的CMD.EXE以及SP2虚拟机安装测试了脚本。它在SP1版本中给出了上述错误结果,但在SP2和SP3版本中工作正常。因此,这确实是一个已修复的bug。对于遇到此问题的任何其他人,SP2+中的CMD.EXE文件可以毫无问题地放入SP1安装中(假设更新不可行)。1-将代码保存在ShortFileName中
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.IO;
using System.Text;
using System.Runtime.InteropServices;
namespace ConvFN
{
class Program
{
static void Main(string[] args)
{
if (args.Length == 3)
{
if ((args[2].Length > 1) && System.IO.File.Exists(args[2]))
{
if (args[1].Equals("-l")) Console.WriteLine(ShortLongFName.GetLongPathName(args[2]));
if (args[1].Equals("-s")) Console.WriteLine(ShortLongFName.ToShortPathName(args[2]));
}
}
}
}
public class ShortLongFName
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern uint GetShortPathName(
[MarshalAs(UnmanagedType.LPTStr)]
string lpszLongPath,
[MarshalAs(UnmanagedType.LPTStr)]
StringBuilder lpszShortPath,
uint cchBuffer);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.U4)]
private static extern int GetLongPathName(
[MarshalAs(UnmanagedType.LPTStr)]
string lpszShortPath,
[MarshalAs(UnmanagedType.LPTStr)]
StringBuilder lpszLongPath,
[MarshalAs(UnmanagedType.U4)]
int cchBuffer);
/// <summary>
/// Converts a short path to a long path.
/// </summary>
/// <param name="shortPath">A path that may contain short path elements (~1).</param>
/// <returns>The long path. Null or empty if the input is null or empty.</returns>
internal static string GetLongPathName(string shortPath)
{
if (String.IsNullOrEmpty(shortPath))
{
return shortPath;
}
StringBuilder builder = new StringBuilder(255);
int result = GetLongPathName(shortPath, builder, builder.Capacity);
if (result > 0 && result < builder.Capacity)
{
return builder.ToString(0, result);
}
else
{
if (result > 0)
{
builder = new StringBuilder(result);
result = GetLongPathName(shortPath, builder, builder.Capacity);
return builder.ToString(0, result);
}
else
{
throw new FileNotFoundException(
string.Format(
CultureInfo.CurrentCulture,
"{0} Not Found",
shortPath),
shortPath);
}
}
}
/// <summary>
/// The ToLongPathNameToShortPathName function retrieves the short path form of a specified long input path
/// </summary>
/// <param name="longName">The long name path</param>
/// <returns>A short name path string</returns>
public static string ToShortPathName(string longName)
{
uint bufferSize = 256;
// don´t allocate stringbuilder here but outside of the function for fast access
StringBuilder shortNameBuffer = new StringBuilder((int)bufferSize);
uint result = GetShortPathName(longName, shortNameBuffer, bufferSize);
return shortNameBuffer.ToString();
}
}
}
Set fso=CreateObject("Scripting.FileSystemObject")
' Is object a file or folder?
If fso.FolderExists(WScript.Arguments(0)) Then
'The dropped stuff is a folder
Set objFolder = fso.GetFolder(WScript.Arguments(0))
rtrn = InputBox("Short path is :", "SHORT PATH", objFolder.ShortPath)
End If
If fso.FileExists(WScript.Arguments(0)) Then
'The dropped stuff is a file
Set objFile = fso.GetFile(WScript.Arguments(0))
rtrn = InputBox("Short path is :", "SHORT PATH", objFile.ShortPath)
End If
%~snx
s ... short
n ... name
x ... extension