حل المطلقة المسار من مسار نسبي و/أو اسم الملف
-
22-07-2019 - |
سؤال
هل هناك طريقة في ويندوز دفعة سيناريو العودة إلى مسار مطلق من قيمة تحتوي على اسم الملف و/أو النسبية الطريق ؟
بالنظر إلى:
"..\"
"..\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