จะทดสอบได้อย่างไรว่าไฟล์ปฏิบัติการมีอยู่ใน% PATH% จากไฟล์แบตช์ของ Windows หรือไม่?


90

ฉันกำลังมองหาวิธีง่ายๆในการทดสอบว่าไฟล์ปฏิบัติการมีอยู่ในตัวแปรสภาพแวดล้อม PATH จากไฟล์แบตช์ของ Windows หรือไม่

ไม่อนุญาตให้ใช้เครื่องมือภายนอกที่ OS ไม่ได้จัดเตรียมไว้ให้ Windows เวอร์ชันขั้นต่ำที่จำเป็นคือ Windows XP



16
@karlphilip: ไม่แน่นอน คำถามที่นี่ค่อนข้างแตกต่างกัน
Joey

1
คุณควรทำเครื่องหมายคำตอบที่ยอมรับ
Jeb

คำตอบ:


70
for %%X in (myExecutable.exe) do (set FOUND=%%~$PATH:X)
if defined FOUND ...

หากคุณต้องการสิ่งนี้สำหรับส่วนขยายที่แตกต่างกันให้ทำซ้ำPATHEXT:

set FOUND=
for %%e in (%PATHEXT%) do (
  for %%X in (myExecutable%%e) do (
    if not defined FOUND (
      set FOUND=%%~$PATH:X
    )
  )
)

อาจเป็นไปได้ว่าwhereมีอยู่แล้วใน Windows รุ่นเก่า แต่ฉันไม่สามารถเข้าถึงได้ดังนั้นฉันจึงไม่สามารถบอกได้ ในเครื่องของฉันสิ่งต่อไปนี้ยังใช้งานได้:

where myExecutable

และส่งคืนด้วยรหัสทางออกที่ไม่ใช่ศูนย์หากไม่พบ ในชุดงานคุณอาจต้องการเปลี่ยนเส้นทางเอาต์พุตไปยังNULด้วย

โปรดทราบ

แยกในชุด ( .bat) ไฟล์และแตกต่างบรรทัดคำสั่ง (เพราะมีไฟล์ batch %0- %9) ดังนั้นคุณต้องไปคู่%มี %Xในบรรทัดคำสั่งนี้ไม่จำเป็นดังนั้นสำหรับตัวแปรที่เป็นเพียง


1
ฉันชอบแนวทางของคุณ แต่จะดีกว่านี้ถ้าคุณสามารถจัดหาเวอร์ชันเต็มซึ่งเป็นเวอร์ชันที่ใช้ PATHEXT สำหรับสิ่งนี้ด้วย
ซอริน

4
สำหรับ XP คุณต้องใช้สคริปต์วนซ้ำ (หรือดาวน์โหลด where.exe จาก RK) Vista และ 7 มาพร้อมกับ where.exe ฉันรู้ว่า OP กล่าวเฉพาะ XP แต่สำหรับคนรุ่นหลังคำตอบที่ดีที่สุดคือต้องใช้where myExecutableเสมอ
Ryan Bemrose

Ryan: หือ? ฉันไม่คิดว่าฉันจะแยกวิเคราะห์ประโยคของคุณได้
Joey

2
ฉันเป็นผู้เริ่มต้นการเขียนสคริปต์เป็นกลุ่มและไม่แน่ใจว่า %% x หมายถึงอะไร ในระบบ Windows 7 ของฉันฉันลองพิมพ์: for %% X in (myExecutable.exe) do (set FOUND = %% ~ $ PATH: X) แล้วกดส่งกลับ ฉันได้รับสิ่งนี้ตอบสนอง: C: \ Users \ James> สำหรับ %% X ใน (cmd.exe) ทำ (ตั้งค่า FOUND = %% ~ $ PATH: X) %% X ไม่คาดคิดในขณะนี้
simgineer

3
simengineer: แยกในไฟล์ batch และแตกต่างบรรทัดคำสั่ง (เพราะมีไฟล์ batch %0- %9) ดังนั้นคุณต้องไปคู่%มี ในบรรทัดคำสั่งนี้ไม่จำเป็นดังนั้นตัวแปรที่เป็นเพียงfor %x
Joey

82

Windows Vista และเวอร์ชันที่ใหม่กว่ามาพร้อมกับโปรแกรมที่เรียกwhere.exeว่าค้นหาโปรแกรมในเส้นทาง มันทำงานดังนี้:

D:\>where notepad
C:\Windows\System32\notepad.exe
C:\Windows\notepad.exe

D:\>where where
C:\Windows\System32\where.exe

สำหรับการใช้งานในไฟล์แบตช์คุณสามารถใช้/qสวิตช์ซึ่งเพิ่งตั้งค่าERRORLEVELและไม่ได้สร้างเอาต์พุตใด ๆ

where /q myapplication
IF ERRORLEVEL 1 (
    ECHO The application is missing. Ensure it is installed and placed in your PATH.
    EXIT /B
) ELSE (
    ECHO Application exists. Let's go!
)

หรือเวอร์ชันชวเลขง่าย ๆ (แต่อ่านได้น้อยกว่า) ที่พิมพ์ข้อความและออกจากแอปของคุณ:

where /q myapplication || ECHO Cound not find app. && EXIT /B

สวยและเรียบง่ายมาก! ขอบคุณ!
Pawel Cioch

18

นี่คือวิธีที่ง่ายที่ความพยายามที่จะเรียกใช้โปรแกรมประยุกต์และจัดการข้อผิดพลาดใด ๆในภายหลัง

file.exe /?  2> NUL
IF NOT %ERRORLEVEL%==9009 ECHO file.exe exists in path

รหัสข้อผิดพลาด 9009 มักจะหมายถึงไม่พบไฟล์

ข้อเสียเพียงอย่างเดียวคือfile.exeจะถูกดำเนินการจริงหากพบ (ซึ่งในบางกรณีไม่สมควร)


25
ข้อเสียเพียงอย่างเดียวคือ "file.exe" ถูกเรียกใช้งาน (ซึ่งในบางกรณีไม่ต้องการ)
eadmaster

6

สิ่งนี้สามารถทำได้โดยการทดแทนพารามิเตอร์

%~$PATH:1

สิ่งนี้ส่งคืนเส้นทางแบบเต็มของชื่อไฟล์ปฏิบัติการใน% 1 ไม่เช่นนั้นจะเป็นสตริงว่าง

สิ่งนี้ใช้ไม่ได้กับตัวแปรที่ผู้ใช้กำหนดเอง ดังนั้นหากชื่อไฟล์ที่เรียกใช้งานได้ไม่ใช่พารามิเตอร์สำหรับสคริปต์ของคุณคุณต้องมีรูทีนย่อย ตัวอย่างเช่น:

call :s_which app.exe
if not "%_path%" == "" (
  "%_path%"
)

goto :eof

:s_which
  setlocal
  endlocal & set _path=%~$PATH:1
  goto :eof

โปรดดูhttp://ss64.com/nt/syntax-args.html


1
เคล็ดลับที่น่าสนใจที่มีsetlocalแต่for %%X in (myExecutable.exe) do (set FOUND=%%~$PATH:X)เป็นวิธีการแก้บรรทัดเดียวกับforที่ใช้เป็นวิธีแก้ปัญหาสำหรับ%%~$PATH:Xในการสั่งซื้อเพื่อหลีกเลี่ยงและcall %~$PATH:1
gavenkoa

0
@echo off
set found=
set prog=cmd.exe
for %%i in (%path%) do if exist %%i\%prog% set found=%%i
echo "%found%"
if "%found%"=="" ....

3
จะไม่ทำงานเนื่องจากforไม่ฉลาดพอที่จะแยกวิเคราะห์เนื้อหาของไฟล์PATH. มันจะพลาดไดเรกทอรีที่มีช่องว่างเช่น และแม้ว่าคุณจะใช้for /fกับdelims=;มันจะทำงานไม่ถูกต้องหากไดเร็กทอรีมี a ;และถูกยกมา
Joey

@ โจอี้แล้วการเปลี่ยนสตริงล่ะ แทนที่;ด้วย"; ": set quotedPath="%PATH:;="; "%".
XP1

1
XP1: ไม่ยังคงไร้ประโยชน์ ลองใช้โดยต่อท้าย"C:\Folder with; semicolon, quoted"เส้นทางและดูว่าเกิดอะไรขึ้น อย่างน้อยก็ลองปฏิบัติต่อ»ทุกคำ«แยกกันซึ่งในทางหนึ่งมันแย่กว่าพฤติกรรมก่อนหน้านี้
Joey

0

บางครั้งวิธีง่ายๆนี้ก็ใช้ได้ผลโดยที่คุณตรวจสอบว่าผลลัพธ์ตรงกับที่คุณคาดหวัง บรรทัดแรกรันคำสั่งและคว้าบรรทัดสุดท้ายของเอาต์พุตมาตรฐาน

FOR /F "tokens=*" %%i in (' "xcopy /? 2> nul" ') do SET xcopyoutput=%%i
if "%xcopyoutput%"=="" echo xcopy not in path.

แต่ถ้าสภาพแวดล้อมของระบบใช้ภาษาอื่นล่ะ?
Beachwalker

0

หากคุณกำลังค้นหาบางอย่างเช่นฉันในโฟลเดอร์เริ่มต้นควรไปที่โฟลเดอร์ ตัวอย่างเช่นฉันค้นหา exe ในโฟลเดอร์เริ่มต้นและฉันใช้รหัสนี้เช่น

@echo off
cd C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
where /q program.exe
IF ERRORLEVEL 1 (
echo F | xcopy /Y /S /I /E "\\programsetup\programsetup.exe" 
"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\program.exe"
) ELSE (
ECHO Application exists. Let's go!
)

แต่จะค้นหาใน PATH แบบเต็มหากprogram.exeมีอยู่ไม่ใช่เฉพาะในโฟลเดอร์เดียว
jeb

-1

ใช้คำสั่ง: powershell Test-Path "exe ที่คุณกำลังมองหา"

มันจะคืนค่า True ถ้าเป็นปัจจุบันมิฉะนั้น False


วิธีนี้ใช้ไม่ได้ Test-Pathตรวจสอบเส้นทางที่ระบุเท่านั้นกล่าวคือTest-Path nuget.exeจะคืนค่าจริงก็ต่อเมื่อnuget.exeอยู่ในไดเร็กทอรีปัจจุบัน หาก nuget.exe ไม่อยู่ในไดเร็กทอรีปัจจุบันจะส่งคืนเท็จแม้ว่าจะอยู่ในไดเร็กทอรีที่แสดงในตัวแปร PATH ก็ตาม ใน PowerShell Get-Commandอาจทำงานได้ดีขึ้น ( stackoverflow.com/questions/11242368/… ) แต่โปรดคำนึงว่าสำหรับ PowerShell ไดเรกทอรีปัจจุบันไม่อยู่ในเส้นทาง
Ronald Zarīts

1
ดังที่ @RonaldZarits ชี้ให้เห็นสำหรับการสนับสนุน PowerShell เต็มรูปแบบคุณสามารถใช้ Get-Command ได้สองตัวเลือก ก่อนอื่นให้ระบุตำแหน่ง dir ปัจจุบันจากนั้นให้ชื่อ exe (Get-Command ".\notepad", "notepad" -ErrorAction Ignore -CommandType Application) -ne $nullจะคืนค่าจริงหากพบในพื้นที่หรือในเส้นทาง
John C

-1

สำหรับผู้ที่มองหาตัวเลือก PowerShell คุณสามารถใช้Get-Commandcmdlet ผ่านสองรายการ ก่อนอื่นให้ระบุตำแหน่ง dir ปัจจุบันพร้อม.\คำนำหน้าจากนั้นให้ชื่อ exe

(Get-Command ".\notepad", "notepad" -ErrorAction Ignore -CommandType Application) -ne $null

ซึ่งจะส่งคืนเป็นจริงหากพบในระบบหรือในเส้นทางกว้าง


ไม่มีอะไรดีไปกว่าการโหวตลงคะแนนและเรียกใช้ผู้ใช้ หากคุณไม่เห็นด้วยและกำลังจะไปไกลถึงการลงคะแนนให้เพิ่มความคิดเห็นเพื่อให้เหตุผลว่าทำไมคุณถึงไม่เห็นด้วยว่านี่ไม่ใช่แนวทางที่ดีในการได้ผลลัพธ์ที่ต้องการ
John C
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.