Làm cách nào để kiểm tra xem tệp thực thi có tồn tại trong% PATH% từ tệp lô cửa sổ hay không?


89

Tôi đang tìm một cách đơn giản để kiểm tra xem tệp thực thi có tồn tại trong biến môi trường PATH từ tệp lô Windows hay không.

Không được phép sử dụng các công cụ bên ngoài không do HĐH cung cấp. Phiên bản Windows tối thiểu được yêu cầu là Windows XP.



15
@karlphilip: Chắc chắn là không. Câu hỏi ở đây là khá khác nhau.
Joey

1
Bạn nên đánh dấu một câu trả lời được chấp nhận.
Jeb

Câu trả lời:


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

Nếu bạn cần điều này cho các tiện ích mở rộng khác nhau, chỉ cần lặp lại PATHEXT:

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

Có thể điều đó wherecũng đã tồn tại trên các phiên bản Windows cũ, nhưng tôi không có quyền truy cập vào một phiên bản, vì vậy tôi không thể nói. Trên máy của tôi, tính năng sau cũng hoạt động:

where myExecutable

và trả về với mã thoát khác 0 nếu không tìm thấy mã này. Tuy nhiên, trong một lô, bạn có thể cũng muốn chuyển hướng đầu ra NUL.

Ghi nhớ

Phân tích cú pháp trong .batcác tệp batch ( ) và trên dòng lệnh khác nhau (vì các tệp batch có %0- %9), vì vậy bạn phải tăng gấp đôi số %ở đó. Trên dòng lệnh, điều này không cần thiết, vì vậy chỉ cần các biến %X.


1
Tôi thích cách tiếp cận của bạn nhưng sẽ tốt hơn nữa nếu bạn có thể cung cấp phiên bản đầy đủ, phiên bản cũng sử dụng PATHEXT cho việc này.
sorin

4
Đối với XP, bạn cần tập lệnh lặp (hoặc tải xuống where.exe từ RK). Vista và 7 đi kèm với where.exe. Tôi biết OP đã nói cụ thể XP, nhưng đối với hậu thế câu trả lời tốt nhất là luôn luôn sử dụng where myExecutable.
Ryan Bemrose,

Ryan: Hả? Tôi không nghĩ rằng tôi có thể phân tích câu của bạn.
Joey

2
tôi là người mới bắt đầu viết tập lệnh hàng loạt và không chắc %% x có nghĩa là gì. Trên hệ thống Windows 7 của mình, tôi đã thử nhập: for %% X in (myExecutable.exe) do (set FOUND = %% ~ $ PATH: X) rồi nhấn trả về. Tôi nhận được điều này theo phản hồi: C: \ Users \ James> for %% X in (cmd.exe) do (set FOUND = %% ~ $ PATH: X) %% X không mong muốn tại thời điểm này.
simgineer

3
simengineer: Phân tích cú pháp trong các tệp hàng loạt và trên dòng lệnh khác nhau (vì tệp hàng loạt có %0- %9), vì vậy bạn phải tăng gấp đôi số %ở đó. Trên dòng lệnh, điều này không cần thiết, vì vậy forcác biến chỉ là %x.
Joey

79

Windows Vista và các phiên bản mới hơn đi kèm với một chương trình được gọi là where.exetìm kiếm các chương trình trong đường dẫn. Nó hoạt động như thế này:

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

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

Để sử dụng trong một tệp hàng loạt, bạn có thể sử dụng công /qtắc, công tắc này chỉ thiết lập ERRORLEVELvà không tạo ra bất kỳ đầu ra nào.

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!
)

Hoặc phiên bản viết tắt đơn giản (nhưng ít đọc hơn) in thông báo và thoát khỏi ứng dụng của bạn:

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

Rất hay và đơn giản! Cảm ơn!
Pawel Cioch

18

Đây là một giải pháp đơn giản cố gắng chạy ứng dụng và xử lý mọi lỗi sau đó .

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

Mã lỗi 9009 thường có nghĩa là không tìm thấy tệp.

Nhược điểm duy nhất là nó file.exethực sự được thực thi nếu được tìm thấy (trong một số trường hợp là không thể giải thích được).


24
chỉ nhược điểm là "file.exe" được thực hiện (mà trong một số trường hợp là không mong muốn)
eadmaster

6

Điều này có thể được thực hiện thông qua thay thế tham số.

%~$PATH:1

Điều này trả về đường dẫn đầy đủ của tên tệp thực thi trong% 1, nếu không là một chuỗi trống.

Điều này không hoạt động với các biến do người dùng xác định. Vì vậy, nếu tên tệp thực thi không phải là một tham số cho tập lệnh của bạn, thì bạn cần một chương trình con. Ví dụ:

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

goto :eof

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

Xem http://ss64.com/nt/syntax-args.html


1
Mẹo thú vị với setlocalnhưng for %%X in (myExecutable.exe) do (set FOUND=%%~$PATH:X)là một giải pháp dòng forđược sử dụng như một giải pháp thay thế %%~$PATH:Xđể tránh 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
Sẽ không hoạt động vì forkhông đủ thông minh để phân tích cú pháp nội dung của PATH. Ví dụ, nó sẽ bỏ lỡ các thư mục có dấu cách. Và ngay cả khi bạn sử dụng for /fvới delims=;nó sẽ không hoạt động chính xác nếu một thư mục chứa một ;và được trích dẫn.
Joey

@Joey, làm thế nào về thay thế chuỗi? Thay thế ;bằng "; ": set quotedPath="%PATH:;="; "%".
XP1

1
XP1: Không, vẫn vô dụng. Hãy thử nó bằng cách gắn "C:\Folder with; semicolon, quoted"vào đường dẫn và xem điều gì sẽ xảy ra. Ít nhất ở đây nó cố gắng xử lý mọi từ «riêng biệt, theo một cách nào đó, là tệ hơn hành vi trước đây.
Joey

0

Đôi khi giải pháp đơn giản này hoạt động, nơi bạn kiểm tra xem đầu ra có khớp với những gì bạn mong đợi hay không. Dòng đầu tiên chạy lệnh và lấy dòng cuối cùng của đầu ra tiêu chuẩn.

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

Nhưng nếu môi trường hệ thống sử dụng một ngôn ngữ khác thì sao?
Beachwalker

0

Nếu bạn đang tìm kiếm một cái gì đó giống như tôi trên thư mục khởi động, hãy chuyển đến thư mục. Ví dụ: tôi tìm kiếm exe trên thư mục khởi động và tôi sử dụng mã này như

@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!
)

Nhưng điều này sẽ tìm kiếm trong PATH đầy đủ nếu program.exetồn tại, không chỉ trong một thư mục
jeb

-1

Sử dụng lệnh: powershell Test-Path "exe mà bạn đang tìm kiếm"

Nó sẽ trả về True nếu hiện tại của nó, ngược lại là False.


Điều này sẽ không hoạt động. Test-Pathchỉ kiểm tra đường dẫn được chỉ định, tức là Test-Path nuget.exesẽ chỉ trả về true nếu nuget.exenằm trong thư mục hiện tại. Nếu nuget.exe không có trong thư mục hiện tại, nó sẽ trả về false, ngay cả khi nó nằm trong thư mục được liệt kê trong biến PATH. Trong PowerShell Get-Commandcó thể hoạt động tốt hơn ( stackoverflow.com/questions/11242368/… ), nhưng hãy lưu ý rằng đối với PowerShell, thư mục hiện tại không có trong đường dẫn.
Ronald Zarīts

1
Như @RonaldZarits đã chỉ ra, để được hỗ trợ đầy đủ PowerShell, bạn có thể sử dụng Get-Command với hai tùy chọn. Đầu tiên cung cấp vị trí dir hiện tại, sau đó chỉ cung cấp tên exe. (Get-Command ".\notepad", "notepad" -ErrorAction Ignore -CommandType Application) -ne $nullsẽ trả về true nếu được tìm thấy cục bộ hoặc trong đường dẫn.
John C,

-1

Đối với những người đang tìm kiếm một tùy chọn PowerShell. Bạn có thể sử dụng Get-Commandlệnh ghép ngắn để chuyển hai mục. Đầu tiên cung cấp vị trí dir hiện tại với .\tiền tố, sau đó chỉ cung cấp tên exe.

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

Điều đó sẽ trả về true nếu được tìm thấy cục bộ hoặc trong các đường dẫn rộng của hệ thống.


Không có gì tốt hơn là downvote và chạy người dùng. Nếu bạn không đồng ý và sẽ đi đến mức phản đối, thì hãy thêm nhận xét để đưa ra lý do khiến bạn không đồng ý rằng đây không phải là một cách tiếp cận tốt để đạt được kết quả mong muốn.
John C
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.