Frage

Mit dem folgenden Befehl in einer Batch-Datei funktioniert nicht wie erwartet / erhofft:

echo %~nxs1


Hier ist ein Beispiel Anzeige von dem, was ich versuche zu bekommen:

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)

Stattdessen, was ich bekommen, ist so etwas wie die folgenden (je nach zugewiesenen Kurzdateinamen):

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



Grundsätzlich, ich brauche einen Dateinamen zu einer BAT Datei übergeben und das Skript erhalten (zB Display) es als Kurzdateinamen, sondern nur die Dateinamen und Erweiterung, kein Laufwerk oder Pfad.

Die Hilfeinformationen für FOR gibt % ~ fsI als Beispiel, aber die den gesamten Pfad als Kurzdateinamen hat, nicht nur die Datei. Wer weiß, wie die S-Parameter von % kombinieren ~ , ohne den gesamten Weg zu bekommen?


Vielen Dank.



Updates

  1. Ich bin nicht für eine Lösung in einer anderen Sprache suchen, muss ich den BAT-Befehl an die Arbeit.

  2. Es scheint, dass es für andere funktioniert, so dass ich überprüft werde, um zu sehen, ob es irgendeine Art von alternativem Konfigurationsproblem ist. Ich teste derzeit, ob Befehlsprozessor-Erweiterungen die Ursache sein könnte.

  3. Es wird überhaupt nicht funktionieren, wenn Erweiterungen deaktiviert (offensichtlich) sind, so dass ich auf der Hypothese werde, dass es ein Fehler ist, die in einem nachfolgenden Service Pack behoben wurden (das System I getestet ist XP SP1). Ich teste SP2 und SP3 heute ...

War es hilfreich?

Lösung

Nun, ich bestätigte es einfach. Getestet habe ich das Skript mit cmd.exe von XP SP1, SP2 und SP3 sowie eine SP2 VM-Installation. Es gab die oben genannten fehlerhaften Ergebnisse mit der SP1-Version, aber funktionierte richtig in den SP2 und SP3-Versionen. So ist es in der Tat ein Problem, das behoben wurde. Für alle anderen, die in diese ausgeführt wird, kann die cmd.exe-Datei von SP2 + in eine SP1-Installation ohne Probleme gelöscht werden (unter der Annahme, dass ein Update nicht möglich ist).

Andere Tipps

Lesen Sie diesem Forum posten . Der Code sieht wie:

%~snx
s ... short 
n ... name
x ... extension

Ich habe kein Problem ausführen Batch. Hoffnung jemand kann Ihnen bald helfen. Aber während Sie gerade dabei sind, hier ist eine Alternative mit Vbscript getan, was ich denke, Sie sollten mit vertraut.

Set objArgs = WScript.Arguments
strFile = objArgs(0)
WScript.Echo CreateObject("Scripting.FileSystemObject").GetFile(strFile).ShortName

auf der Kommandozeile (oder Batch), nennen Sie es wie diese

C:\test>cscript //nologo getshortname.vbs "C:\Documents and Settings\All Users\Desktop\shortcut.lnk"
shortcut.lnk

1- Speichern Sie den Code in ShortFileName.Vbs

2- Drag n Drop-beliebige Ordner oder eine Datei zu diesem Skript

    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

Es gibt einen anderen Weg, dies zu tun, kompilieren Sie diesen Code in 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 &gt; 0 && result &lt; builder.Capacity)
            {
                return builder.ToString(0, result);
            }
            else
            {
                if (result &gt; 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();
        }
    }
}

Fügen Sie diese in die Konsole C # Projekt namens ConvFN und es bauen. Dann rufen Sie ConvFN es% 1 aus der Batch-Datei, in der die Parameter% 1 sind eineine langen Dateinamen und gibt er die kurzen Dateinamen äquivalent ... wie weise die inversen, ConvFN -l% 1% 1, wo die kurzen Dateinamen und gibt er die langen Dateinamen gleichwertig.

Dieser Code wurde entnommen aus pinvoke.net.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top