批处理文件中的以下命令无法按预期/希望工作:
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)
相反,我得到的是以下内容(取决于指定的短文件名):
C:\>type test.bat
@dir /b %1
@echo %~nxs1
C:\>test "C:\Documents and Settings\All Users\ntuser.dat"
ntuser.dat
s\ntuser.dat
C:\>test "C:\Documents and Settings\All Users\ntuser.data"
ntuser.data
s\ntuser.data
C:\>test "C:\Documents and Settings\All Users\ntuser.dat.baz"
ntuser.dat.baz
z
C:\>test "C:\Documents and Settings\All Users\foo.bar.baz"
File Not Found
s\foo.bar.baz
基本上,我需要将文件名传递给 BAT 文件并让脚本获取(例如显示)为短文件名,但只有文件名和扩展名,没有驱动器或路径。
FOR 的帮助信息以%~fsi 为例,但它的整个路径为短文件名,而不仅仅是文件。有没有人知道如何结合%〜的S参数而不获取整个路径?
非常感谢。
更新
我不是在寻找其他语言的解决方案,我需要使用BAT命令。
它似乎适用于其他人,所以我正在检查它是否是某种备用配置问题。我正在测试是否可能是Command Processor Extensions的原因。
如果Extensions被禁用(显然),它根本不起作用,所以我假设这是一个在后续Service Pack中修复的错误(我测试的系统是XP SP1)。我今天正在测试SP2和SP3 ......
答案 0 :(得分:2)
我刚刚确认了。我在XP SP1,SP2和SP3以及SP2 VM安装中使用CMD.EXE测试了脚本。它在SP1版本中给出了上述错误结果,但在SP2和SP3版本中正常工作。所以这确实是一个被修复的错误。对于遇到此问题的其他任何人,可以将SP2 +中的CMD.EXE文件放入SP1安装中而不会出现问题(假设更新不可行)。
答案 1 :(得分:2)
看看this forum post。代码如下:
%~snx
s ... short
n ... name
x ... extension
答案 2 :(得分:0)
执行批处理时没有问题。希望有人能尽快帮助你。但是当你在这里时,这是用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
答案 3 :(得分:0)
还有另一种方法,在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();
}
}
}
将其添加到名为ConvFN的Console C#项目中并构建它。然后从批处理文件中调用ConvFN -s%1,其中%1参数是一个长文件名,它将输出等效的短文件名...就像明智的逆,ConvFN -l%1其中%1是短文件名,它将输出等效的长文件名。
此代码取自pinvoke.net。
答案 4 :(得分:0)
1-保存ShortFileName.Vbs中的代码
2-拖放任何文件夹或文件到此脚本
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