Có cách nào để lấy shell cmd windows để mở rộng đường dẫn ký tự đại diện không?


37

Đôi khi, việc cmd shell không có khả năng mở rộng đường dẫn ký tự đại diện thực sự có thể là một sự bất tiện. Tôi đã phải chuyển 100 tệp trong một thư mục cho một chương trình và không thể gõ * .ext. Thay vào đó, tôi đã sử dụng 'ls' của mingw để kết xuất danh sách vào một tệp, sau đó thay thế các dòng mới bằng dấu cách, sao chép và dán vào cmd. Khá là một cơn ác mộng.

Tôi nghi ngờ câu trả lời sẽ là không, nhưng có ai đã xử lý vấn đề này hay đưa ra bất kỳ cách nào để làm cho việc này dễ dàng hơn không?


2
Bạn đã xem xét sử dụng một cái gì đó như Powershell thay thế?

I suspect the answer will be no, but has anyone dealt with this or come up with any way to make this easier? Trên thực tế, tôi đang gặp vấn đề ngược lại, tôi đang cố gắng tìm ra cách để trình thông dịch lệnh xử lý danh sách của nó dưới dạng chuỗi và ngăn không cho chúng trả lời chúng dưới dạng ký tự đại diện. Ví dụ, for %i in (foobar baz really?) do @echo %isẽ đối xử với mục cuối cùng ( really?) như là một ký tự đại diện tên tập tin, và bỏ qua nó nếu không có tập tin có tên really1, reallyzvv ☹
Synetech

1
@Synetech - ?không phải là ký tự hợp pháp cho tên tệp trong hệ thống tệp Windows. Ký tự chỉ có thể được hiểu là ký tự đại diện. Xem Đặt tên tệp, đường dẫn và không gian tên trên MSDN và sử dụng các ký tự đại diện trong TechNet.
jww

Câu trả lời:


18

DOS, và do đó, Windows ' cmd.exe, không bao giờ hỗ trợ mở rộng ký tự đại diện. Nó luôn luôn phụ thuộc vào ứng dụng để thực hiện việc mở rộng.

Điều này có nghĩa là bạn sẽ luôn phải tìm một tuyến đường khác nếu bạn đang sử dụng một ứng dụng không hỗ trợ mở rộng. Bạn có thể:

  • Sử dụng vòng lặp FOR để chạy một số lệnh đối với tất cả các tệp bạn quan tâm
  • Sử dụng dir /b > list.txtđể sử dụng dirlệnh để thực hiện mở rộng và đưa danh sách các tệp vào tệp văn bản (sau đó bạn có thể sử dụng một cái gì đó giống như công thức Excel nếu bạn thực sự mong muốn tạo danh sách các lệnh để dán vào cmdhoặc bạn có thể sử dụng Excel để hoán vị các ô sao cho tất cả các tên tệp nằm trên cùng một dòng.)

Ông giải thích rằng sẽ là một cơn ác mộng khi đưa kết quả của dir vào một tệp và xử lý quá trình lọc và sao chép thủ công. Câu trả lời của wmz và tất nhiên là của tôi sẽ hoạt động mà không cần lọc thủ công một nội dung tệp.
wullxz

1
@wullxz: Có lẽ, nhưng đối với một người không quen thuộc với Powershell muốn làm điều này một lần, nó có thể nhanh hơn đáng kể - và ý tưởng đằng sau trang web này là cung cấp các giải pháp hữu ích cho mọi người ở mọi cấp độ kỹ năng để tham khảo ngay bây giờ và trong tương lai, vì vậy thực sự không cần phải nói với tôi vì bạn nghĩ câu trả lời của tôi không tốt bằng của bạn.
Malvineous

1
"DOS, và do đó, cmd.exe của Windows, không bao giờ hỗ trợ mở rộng ký tự đại diện bằng shell." - Không đúng theo Microsoft. Xem Sử dụng ký tự đại diện trên TechNet. (Nhưng tôi nghĩ rằng bạn đã đúng trong thực tế: o. Nếu không, tôi sẽ không ở đây để cố gắng tìm ra lý do tại sao các tệp không khớp)
jww

1
@jww: Liên kết bạn đã đăng giải thích việc sử dụng tiêu chuẩn của các ký tự đại diện, nhưng tôi không thể thấy bất kỳ đề cập nào về chúng được mở rộng bởi trình bao. Không giống như UNIX (và sau này là Linux và Mac), Microsoft đã mở rộng ký tự đại diện cho từng ứng dụng riêng lẻ để thực hiện, chuyển các tham số dòng lệnh thông qua nguyên trạng.
Malvineous

1
Lệnh DOS 'dir Filespec / b' hoạt động thực sự tốt, bởi vì nó tạo ra một danh sách các tệp, mỗi tệp trên một dòng. Với công tắc '/ s' bổ sung, tên tệp hoàn toàn đủ điều kiện (tuyệt đối) và có thể dễ dàng được cung cấp qua vòng lặp for cho bất kỳ chương trình dòng lệnh nào khác có tên tệp. Đó là điều tốt nhất chúng ta có thể làm, vì Windows không có tính năng toàn cầu hóa phù hợp.
David A. Gray

9

Chỉ cần sử dụng Powershell, được cài đặt sẵn trên Windows 7. Powershell có khả năng chạy các lệnh cmd và không hiểu các ký tự đại diện tại bất kỳ vị trí nào trong một đường dẫn.

Để bắt đầu Powershell, chỉ cần gõ "powershell" trong hộp tìm kiếm menu bắt đầu của bạn và nhấn enter.


Trong trường hợp ứng dụng mong đợi một chuỗi có tất cả tên tệp trong đó thì đây là tập lệnh đúng:

$delimiter = " "
[string]$files = $nothing ; ls *.txt | % { $files += $_.fullname + $delimiter } ; application.exe $files

Thay đổi $delimiter = " "thành $delimiter = ","nếu ứng dụng của bạn mong đợi một danh sách tên tệp được phân tách bằng dấu phẩy.

Giải thích về mã:

  • [string]$files = $nothing - tạo ra một biến rỗng của loại string
  • ; - là một dấu phân cách cho nhiều lệnh, không phải là đường ống!
  • ls *.txt | % { $files += $_.fullname + $delimiter } - lấy danh sách tất cả các tệp văn bản và tạo một chuỗi với tất cả các tên tệp được phân tách bằng dấu phân cách
  • application.exe $files - gọi ứng dụng và chuyển danh sách tệp cho nó

Bạn thậm chí có thể tìm kiếm một mẫu tệp đệ quy bằng cách thêm -recursevào ls *.txtđể mã hoàn chỉnh sẽ trông như thế này:

$delimiter = " "
[string]$files = $nothing ; ls *.txt -recurse | % { $files += $_.fullname + $delimiter } ; application.exe $files

Chỉnh sửa:
Để tránh kích thích, lsdirlà bí danh Get-ChildItem%là bí danh ForEach-Object. Tôi giữ mã của mình với các bí danh được sử dụng vì nó ngắn hơn.

EDIT 2018/04/25:
Quay trở lại năm 2012 Tôi đã khá mới với PowerShell. Tất nhiên có một cách dễ dàng hơn mặc dù nó không dễ như khả năng mở rộng toàn cầu của unix / linux:

app.exe $(ls *.txt | % {$_.FullName})

Giải trình:

  • $ () sẽ đánh giá biểu thức bên trong trước và sẽ thay thế chính nó bằng đầu ra của biểu thức đó (giống như backticks làm trong bash)
  • ls *.txt lấy các đối tượng FileInfo của tất cả các tệp khớp với toàn cục *.txt
  • vì PowerShell được định hướng đối tượng, chúng tôi phải xuất tên đầy đủ của từng đối tượng FileInfo. Chỉ cần đặt tên một thuộc tính / thuộc tính trong PowerShell sẽ xuất nó theo mặc định. % { $_.FileName }làm điều đó cho chúng tôi. %vòng lặp trên tất cả các phần tử được trả về lsvà xuất ra từng đối tượng FileName.

2
Alhough PS chắc chắn có khả năng đáp ứng yêu cầu và lời khuyên để làm quen với nó là âm thanh - nó không đơn giản như bạn đề xuất. Chạy start notepad++ *.txt(với ý định để mở tất cả textfiles - đã qua sử dụng notepad ++ vì nó không xử lý nhiều tên) sẽ giúp bạn có được đâu
WMZ

1
Bạn có thể giải quyết mà với dir *.txt | % { notepad++.exe $_ }. Tôi đã thử điều đó với notepad đơn giản, vì tôi không có notepad ++ và nó đã hoạt động. Lệnh nhận danh sách tất cả các tệp txt trong thư mục hiện tại, chuyển danh sách sang lệnh tiếp theo lặp qua danh sách và thực thi notepad ++ với tên tệp là tham số.
wullxz

có, nhưng điều này không tương đương. Hãy suy nghĩ về grep "a b c"việc tìm bất kỳ chuỗi nào được liệt kê, trong đó "ab c" sẽ được mở rộng danh sách
wmz

5
Chạy một lệnh với danh sách các mục làm tham số không tương đương với chạy lệnh nhiều lần với mỗi phần tử từ danh sách dưới dạng tham số. Một ví dụ khác: copy a+b+c resultcopy a result copy b result copy c result. (và grep như tiện ích tồn tại trong PS, nó được gọi là select-string)
wmz

1
được khuyến khích, nhưng thật đáng tiếc khi OP không quan tâm đến việc giải thích ...
wmz

8

Điều này sẽ cung cấp cho bạn một danh sách và cũng đặt nó trong biến có tên expanded_list. Đặt nó trong tập tin hàng loạt và chạy với myBatchFile name myPattern. Mẫu kèm theo dấu ngoặc kép nếu nó bao gồm khoảng trắng. Khớp các tập tin, không có thư mục. Chạy mà không có thông số phù hợp với tất cả.

@echo off
set expanded_list=
for /f "tokens=*" %%F in ('dir /b /a:-d "%~1"') do call set expanded_list=%%expanded_list%% "%%F"

echo expanded_list is: 
echo %expanded_list%

Sau đó bạn có thể chạy lệnh của bạn với my_command_exec %expanded_list%

CẢNH BÁO! Kích thước tối đa của biến cmd là 8191 ký tự (XP trở đi), vì vậy có thể vượt qua nó! Bạn không thể tin tưởng vào tiện ích để luôn cung cấp cho bạn danh sách đầy đủ. Mặt khác, chiều dài dòng cmd tối đa cũng là 8191, do đó bạn sẽ không thể thực hiện nó.


Lưu ý nếu không có đối số nào được chỉ định thì extend_list sẽ được đặt thành tất cả các tệp trong thư mục hiện tại có thể hoặc không phải là điều mong muốn vì vậy có thể muốn thêm kiểm tra để không có đối số (ví dụ: "% 1" == "" ...)
JasonM1

3

Điều này hoạt động trong cmd.exe

dir /b *.ext

hoặc là

echo | dir /b *.ext

Điều này chỉ hoạt động cho tên tệp, không phải bất kỳ phần nào của đường dẫn. Ví dụ dir /b TortoiseSVN\bin\sv*.exesẽ hiển thị svn.exesvnadmin.exe. Nhưng dir /b TortoiseSVN\bi*\svn.exehiển thị một lỗi cú pháp.
styfle

1
kiểm tra dir /s /b. Điều này cung cấp cho bạn con đường đầy đủ.
WesternGun

3

Lưu ý, đây là trong Nhận xét cho người đăng trong một chủ đề riêng biệt619818 và styfle)

DIR có thể và không cho phép tìm kiếm tất cả các thư mục con cho các tệp khớp với một loại cụ thể.

Lưu ý: Thư mục gốc để kiểm tra tất cả các thư mục con nằm dưới được giả sử là "C: \ Chương trình của tôi \ Root \" vì tác giả không đặt tên đường dẫn theo đó các thư mục này được đặt

DIR /B /S "C:\My Program\Root\*.ext"

điều này sẽ cung cấp đường dẫn tệp đầy đủ và tên tệp của tệp nguồn.

nếu bạn chỉ muốn tên tập tin, bạn sẽ phải làm như sau

FOR /F "Tokens=*" %A IN ('DIR /B /S "C:\My Program\Root\*.ext"') DO @( Echo.%~nxA )

vì vậy, giả sử bạn muốn chuyển tất cả các tệp này từ "C: \ Chương trình của tôi \ Root \ Sub Directories \ *. ext" sang "D: \ Singlefolder \ *. ext", bạn chỉ cần làm điều này:

FOR /F "Tokens=*" %A IN ('DIR /B /S "C:\My Program\Root\*.ext"') DO @( MOVE "%~A" "D:\Singlefolder\%~nxA" /Y )

Hy vọng rằng sẽ giúp đỡ người khác trong tương lai. :)


1

Điều này đã cũ, nhưng với hệ thống con Linux cho các cửa sổ, việc sử dụng bash trong PATH của bạn là khá phổ biến. Nếu đó là trường hợp, thì điều này có thể làm cho bạn mẹo:

bash -c 'cat *.txt'

lưu ý rằng các trích dẫn đơn không đặc biệt trong cmd Windows , do đó nếu bạn chạy lệnh trên từ cmd thì nó sẽ không hoạt động. Và điều này cũng áp dụng cho các hệ thống có Cygwin hoặc các môi trường bash khác
phuclv
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.