سؤال

هل هناك طريقة في ويندوز دفعة سيناريو العودة إلى مسار مطلق من قيمة تحتوي على اسم الملف و/أو النسبية الطريق ؟

بالنظر إلى:

"..\"
"..\somefile.txt"

أنا في حاجة إلى المسار المطلق بالنسبة إلى ملف دفعي.

على سبيل المثال:

  • "somefile.txt" يقع في "C:\Foo\"
  • "اختبار.الخفافيش" يقع في "C:\Foo\Bar".
  • المستخدم فتح نافذة الأوامر في "C:\Foo" و المكالمات Bar\test.bat ..\somefile.txt
  • في الملف الدفعي "C:\Foo\somefile.txt" قد تكون مشتقة من %1
هل كانت مفيدة؟

المحلول

في الملفات الدفعية، كما هو الحال في برامج C القياسية، تحتوي الوسيطة 0 على المسار إلى البرنامج النصي الذي يتم تنفيذه حاليًا.يمكنك استخدام %~dp0 للحصول على جزء المسار من الوسيطة 0 فقط (وهو البرنامج النصي الحالي) - يكون هذا المسار دائمًا مسارًا مؤهلاً بالكامل.

يمكنك أيضًا الحصول على المسار المؤهل بالكامل للوسيطة الأولى باستخدام %~f1, ، ولكن هذا يعطي مسارًا وفقًا لدليل العمل الحالي، والذي من الواضح أنه ليس ما تريده.

شخصيا، غالبا ما أستخدم %~dp0%~1 المصطلح في الملف الدفعي الخاص بي، والذي يفسر الوسيطة الأولى المتعلقة بمسار الدفعة المنفذة.على الرغم من أنه يحتوي على عيب:إنه يفشل فشلاً ذريعًا إذا كانت الوسيطة الأولى مؤهلة بالكامل.

إذا كنت بحاجة إلى دعم كل من الأقارب و المسارات المطلقة، يمكنك الاستفادة منها حل فريديريك مينيز:تغيير دليل العمل الحالي مؤقتًا.

فيما يلي مثال يوضح كلًا من هذه التقنيات:

@echo off
echo %%~dp0 is "%~dp0"
echo %%0 is "%0"
echo %%~dpnx0 is "%~dpnx0"
echo %%~f1 is "%~f1"
echo %%~dp0%%~1 is "%~dp0%~1"

rem Temporarily change the current working directory, to retrieve a full path 
rem   to the first parameter
pushd .
cd %~dp0
echo batch-relative %%~f1 is "%~f1"
popd

إذا قمت بحفظ هذا كـ c: emp\example.bat وقمت بتشغيله من c:\Users\Public كـ

c:\Users\Public> emp\example.bat ..\windows

...ستلاحظ الإخراج التالي:

%~dp0 is "C:\temp\"
%0 is "\temp\example.bat"
%~dpnx0 is "C:\temp\example.bat"
%~f1 is "C:\Users\windows"
%~dp0%~1 is "C:\temp\..\windows"
batch-relative %~f1 is "C:\Windows"

يمكن العثور على الوثائق الخاصة بمجموعة المعدلات المسموح بها في الوسيطة الدفعية هنا:https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/call

نصائح أخرى

لقد صادفتني حاجة مماثلة هذا الصباح:كيفية تحويل المسار النسبي إلى مسار مطلق داخل برنامج نصي لأوامر Windows.

ما يلي فعلت الحيلة:

@echo off

set REL_PATH=..\..\
set ABS_PATH=

rem // Save current directory and change to target directory
pushd %REL_PATH%

rem // Save value of CD variable (current directory)
set ABS_PATH=%CD%

rem // Restore original directory
popd

echo Relative path: %REL_PATH%
echo Maps to path: %ABS_PATH%

تبدو معظم هذه الإجابات مجنونة بسبب التعقيد والعربات التي تجرها الدواب، وإليك إجابتي -- إنها تعمل على أي متغير بيئة، لا %CD% أو PUSHD/POPD, ، أو for /f هراء - مجرد وظائف دفعة قديمة.- لا يجب أن يكون الدليل والملف موجودين.

CALL :NORMALIZEPATH "..\..\..\foo\bar.txt"
SET BLAH=%RETVAL%

ECHO "%BLAH%"

:: ========== FUNCTIONS ==========
EXIT /B

:NORMALIZEPATH
  SET RETVAL=%~dpfn1
  EXIT /B

دون الحاجة إلى الحصول على ملف دفعي آخر لتمرير الوسائط إليه (واستخدام عوامل تشغيل الوسائط)، يمكنك استخدامه FOR /F:

FOR /F %%i IN ("..\relativePath") DO echo absolute path: %%~fi

أين ال i في %%~fi هو المتغير المحدد في /F %%i.على سبيل المثال.إذا قمت بتغيير ذلك إلى /F %%a ثم سيكون الجزء الأخير %%~fa.

للقيام بنفس الشيء مباشرة في موجه الأوامر (وليس في ملف دفعي) استبدل %% مع %...

هذا للمساعدة في ملء الفجوات في إجابة Adrien Plisson (والتي يجب التصويت عليها بمجرد قيامه بتحريرها؛-):

يمكنك أيضًا الحصول على المسار المؤهل بالكامل للوسيطة الأولى باستخدام %~f1، ولكن هذا يعطي مسارًا وفقًا للمسار الحالي، وهو ما لا تريده بوضوح.

لكن للأسف لا أعرف كيف أجمع بين الاثنين معاً..

يمكن للمرء أن يتعامل %0 و %1 على نفس المنوال:

  • %~dpnx0 للحصول على محرك + مسار + اسم + ملحق مؤهل بالكامل للملف الدفعي نفسه،
    %~f0 ويكفي أيضاً؛
  • %~dpnx1 للحصول على محرك + مسار + اسم + ملحق مؤهل بالكامل للوسيطة الأولى [إذا كان هذا اسم ملف على الإطلاق]،
    %~f1 ويكفي أيضاً؛

%~f1 ستعمل بشكل مستقل عن كيفية تحديد الوسيطة الأولى:بمسارات نسبية أو بمسارات مطلقة (إذا لم تحدد امتداد الملف عند التسمية %1, ، لن تتم إضافته، حتى لو كنت تستخدمه %~dpnx1 -- لكن.

ولكن كيف بحق السماء يمكنك تسمية ملف على محرك أقراص مختلف على أي حال، إذا كنت لن تعطي معلومات المسار الكاملة في سطر الأوامر في المقام الأول؟

لكن، %~p0, %~n0, %~nx0 و %~x0 قد يكون مفيدًا، إذا كنت مهتمًا بالمسار (بدون حرف محرك الأقراص)، أو اسم الملف (بدون امتداد)، أو اسم الملف الكامل بامتداد أو امتداد اسم الملف فقط.ولكن ملاحظة، في حين %~p1 و %~n1 سيعمل على معرفة مسار أو اسم الوسيطة الأولى، %~nx1 و %~x1 لن يقوم add+show بالامتداد، إلا إذا استخدمته في سطر الأوامر بالفعل.

يمكنك أيضًا استخدام وظائف الدُفعات لهذا:

@echo off
setlocal 

goto MAIN
::-----------------------------------------------
:: "%~f2" get abs path of %~2. 
::"%~fs2" get abs path with short names of %~2.
:setAbsPath
  setlocal
  set __absPath=%~f2
  endlocal && set %1=%__absPath%
  goto :eof
::-----------------------------------------------

:MAIN
call :setAbsPath ABS_PATH ..\
echo %ABS_PATH%

endlocal

تحسين صغير ل الحل الأمثل لـ BrainSlugs83.معمم للسماح بتسمية متغير بيئة الإخراج في المكالمة.

@echo off
setlocal EnableDelayedExpansion

rem Example input value.
set RelativePath=doc\build

rem Resolve path.
call :ResolvePath AbsolutePath %RelativePath%

rem Output result.
echo %AbsolutePath%

rem End.
exit /b

rem === Functions ===

rem Resolve path to absolute.
rem Param 1: Name of output variable.
rem Param 2: Path to resolve.
rem Return: Resolved absolute path.
:ResolvePath
    set %1=%~dpfn2
    exit /b

إذا هربت من C:\project الإخراج هو:

C:\project\doc\build

أنا لم أر الكثير من الحلول لهذه المشكلة.بعض الحلول الاستفادة من اجتياز الدليل باستخدام القرص المضغوط وغيرها الاستفادة من الدفعة وظائف.بلدي تفضيل شخصي تم دفعة وظائف على وجه الخصوص ، MakeAbsolute وظيفة على النحو المنصوص عليه من قبل DosTips.

وظيفة له بعض الفوائد الحقيقية في المقام الأول أنه لا تغيير دليل العمل الحالي وثانيا أن المسارات التي يجري تقييمها حتى لا يكون في الوجود.يمكنك أن تجد بعض النصائح المفيدة حول كيفية استخدام الدالة هنا أيضا.

هنا هو مثال على السكربت و نتائجها:

@echo off

set scriptpath=%~dp0
set siblingfile=sibling.bat
set siblingfolder=sibling\
set fnwsfolder=folder name with spaces\
set descendantfolder=sibling\descendant\
set ancestorfolder=..\..\
set cousinfolder=..\uncle\cousin

call:MakeAbsolute siblingfile      "%scriptpath%"
call:MakeAbsolute siblingfolder    "%scriptpath%"
call:MakeAbsolute fnwsfolder       "%scriptpath%"
call:MakeAbsolute descendantfolder "%scriptpath%"
call:MakeAbsolute ancestorfolder   "%scriptpath%"
call:MakeAbsolute cousinfolder     "%scriptpath%"

echo scriptpath:       %scriptpath%
echo siblingfile:      %siblingfile%
echo siblingfolder:    %siblingfolder%
echo fnwsfolder:       %fnwsfolder%
echo descendantfolder: %descendantfolder%
echo ancestorfolder:   %ancestorfolder%
echo cousinfolder:     %cousinfolder%
GOTO:EOF

::----------------------------------------------------------------------------------
:: Function declarations
:: Handy to read http://www.dostips.com/DtTutoFunctions.php for how dos functions
:: work.
::----------------------------------------------------------------------------------
:MakeAbsolute file base -- makes a file name absolute considering a base path
::                      -- file [in,out] - variable with file name to be converted, or file name itself for result in stdout
::                      -- base [in,opt] - base path, leave blank for current directory
:$created 20060101 :$changed 20080219 :$categories Path
:$source http://www.dostips.com
SETLOCAL ENABLEDELAYEDEXPANSION
set "src=%~1"
if defined %1 set "src=!%~1!"
set "bas=%~2"
if not defined bas set "bas=%cd%"
for /f "tokens=*" %%a in ("%bas%.\%src%") do set "src=%%~fa"
( ENDLOCAL & REM RETURN VALUES
    IF defined %1 (SET %~1=%src%) ELSE ECHO.%src%
)
EXIT /b

و الإخراج:

C:\Users\dayneo\Documents>myscript
scriptpath:       C:\Users\dayneo\Documents\
siblingfile:      C:\Users\dayneo\Documents\sibling.bat
siblingfolder:    C:\Users\dayneo\Documents\sibling\
fnwsfolder:       C:\Users\dayneo\Documents\folder name with spaces\
descendantfolder: C:\Users\dayneo\Documents\sibling\descendant\
ancestorfolder:   C:\Users\
cousinfolder:     C:\Users\dayneo\uncle\cousin

آمل أن يساعد هذا...بالتأكيد ساعدني :) P. S.شكرا مرة أخرى إلى DosTips!أنت رائعة!

في المثال الخاص بك، من Bar est.bat، سيرجع DIR /B /S ..\somefile.txt المسار الكامل.

يمكنك فقط تسلسلها.

SET ABS_PATH=%~dp0 
SET REL_PATH=..\SomeFile.txt
SET COMBINED_PATH=%ABS_PATH%%REL_PATH%

يبدو الأمر غريبًا مع وجود \..\ في منتصف طريقك ولكنه يعمل.لا داعي لفعل أي شيء مجنون :)

يعد PowerShell شائعًا جدًا هذه الأيام، لذا أستخدمه كثيرًا كطريقة سريعة لاستدعاء C# نظرًا لأنه يحتوي على وظائف لكل شيء تقريبًا:

@echo off
set pathToResolve=%~dp0\..\SomeFile.txt
for /f "delims=" %%a in ('powershell -Command "[System.IO.Path]::GetFullPath( '%projectDirMc%' )"') do @set resolvedPath=%%a

echo Resolved path: %resolvedPath%

إنه بطيء بعض الشيء، ولكن من الصعب التغلب على الوظائف المكتسبة إلا دون اللجوء إلى لغة برمجة نصية فعلية.

يعمل حل stijn مع المجلدات الفرعية ضمن C:\Program Files (86)\,

@echo off
set projectDirMc=test.txt

for /f "delims=" %%a in ('powershell -Command "[System.IO.Path]::GetFullPath( '%projectDirMc%' )"') do @set resolvedPath=%%a

echo full path:    %resolvedPath%

ملفات انظر جميع الإجابات الأخرى

الدلائل

مع .. كونه المسار النسبي الخاص بك، وعلى افتراض أنك موجود حاليًا D:\Projects\EditorProject:

cd .. & cd & cd EditorProject (المسار النسبي)

إرجاع المسار المطلق على سبيل المثال

D:\Projects

SET CD=%~DP0

SET REL_PATH=%CD%..\..\build\

call :ABSOLUTE_PATH    ABS_PATH   %REL_PATH%

ECHO %REL_PATH%

ECHO %ABS_PATH%

pause

exit /b

:ABSOLUTE_PATH

SET %1=%~f2

exit /b
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top