Cách lặp qua các tệp khớp với ký tự đại diện trong tệp bó


193

Tôi có một bộ tên tệp cơ sở, với mỗi tên 'f' có chính xác hai tệp, 'f.in' và 'f.out'. Tôi muốn viết một tệp bó (trong Windows XP) đi qua tất cả các tên tệp, cho mỗi tệp nên:

  • Hiển thị tên cơ sở 'f'
  • Thực hiện một hành động trên 'f.in'
  • Thực hiện một hành động khác trên 'f.out'

Tôi không có cách nào để liệt kê tập hợp tên tệp cơ sở, ngoài việc tìm kiếm * .in (hoặc * .out) chẳng hạn.


10
Tôi thực sự không muốn trở thành anh chàng này sau 111/0 phiếu bầu, nhưng câu hỏi của bạn không cho thấy bất kỳ cuộc tìm kiếm nào
phil294

Câu trả lời:


292

Giả sử bạn có hai chương trình xử lý hai tệp, process_in.exe và processDef.exe:

for %%f in (*.in) do (
    echo %%~nf
    process_in "%%~nf.in"
    process_out "%%~nf.out"
)

%% ~ nf là công cụ sửa đổi thay thế, chỉ mở rộng% f thành tên tệp. Xem các sửa đổi khác trong https://technet.microsoft.com/en-us/l Library / bb490909.aspx (ở giữa trang) hoặc chỉ trong câu trả lời tiếp theo.


47
Sử dụng một '%' duy nhất nếu gõ này trên dòng lệnh. Tôi biết OP không hỏi về dòng lệnh, nhưng đó là những gì tôi đang tìm kiếm khi câu hỏi này xuất hiện ở đầu tìm kiếm Google của tôi. Những người khác có thể đánh giá cao bit này.
Jason

2
Bạn có thể giải thích cú pháp? Biến vòng lặp được khai báo %%ftại sao lại %%~nfmuộn hơn?
Đại tá Panic

6
@ColonelPanic - có một số ~sửa đổi để làm mọi thứ, như trong ví dụ của tôi, chỉ cần lấy tên tệp. Đó chỉ là thói quen của tôi để sử dụng nó trong trường hợp *đường dẫn đầy đủ hoặc thứ gì đó. Có một số ít các sửa đổi này (ở giữa trang): microsoft.com/resource/documentation/windows/xp/all/proddocs/ Lỗi
Jim Buck

Điều gì nếu tập tin và thư mục có không gian trong đó?
BKSpurgeon

3
Ngoài ra, hãy lưu ý rằng biến %% f phải là một chữ cái - thông báo lỗi khó hiểu sẽ xuất hiện nếu bạn cố gắng sử dụng thứ gì đó dễ đọc và có ý nghĩa.
Bruce Dawson

90

Bạn có thể sử dụng dòng này để in nội dung của máy tính để bàn của bạn:

FOR %%I in (C:\windows\desktop\*.*) DO echo %%I 

Khi bạn có %%Ibiến, thật dễ dàng để thực hiện một lệnh trên nó (chỉ cần thay thế từ echo bằng chương trình của bạn)

Ngoài ra, việc thay thế các tham chiếu biến FOR đã được tăng cường Bây giờ bạn có thể sử dụng cú pháp tùy chọn sau:

%~I         - expands %I removing any surrounding quotes (")
%~fI        - expands %I to a fully qualified path name
%~dI        - expands %I to a drive letter only
%~pI        - expands %I to a path only (directory with \)
%~nI        - expands %I to a file name only
%~xI        - expands %I to a file extension only
%~sI        - expanded path contains short names only
%~aI        - expands %I to file attributes of file
%~tI        - expands %I to date/time of file
%~zI        - expands %I to size of file
%~$PATH:I   - searches the directories listed in the PATH
               environment variable and expands %I to the
               fully qualified name of the first one found.
               If the environment variable name is not
               defined or the file is not found by the
               search, then this modifier expands to the
               empty string

https://ss64.com/nt/syntax-args.html

Trong các ví dụ trên %Ivà PATH có thể được thay thế bằng các giá trị hợp lệ khác. Các %~cú pháp được chấm dứt bởi một tên biến CHO hợp lệ. Chọn các tên biến chữ hoa như %Ilàm cho nó dễ đọc hơn và tránh nhầm lẫn với các sửa đổi, không phân biệt chữ hoa chữ thường.

Bạn có thể lấy tài liệu đầy đủ bằng cách gõ FOR /?


Điều này dường như không hoạt động. %%I was unexpected at this time.
Brad

4
@Brad nếu bạn đang sử dụng điều này trong dòng lệnh (chứ không phải trong tệp bó), thì hãy sử dụng %Ithay vì%%I
doubleDown

1
Một câu trả lời tốt hơn nhiều so với chấp nhận. Tất cả các cờ / công cụ sửa đổi có trong câu trả lời và không phải trang web của bên thứ ba ( không ai muốn nhấp vào liên kết của bạn, Louis )
JustCarty

5

Cách dễ nhất, như tôi thấy, là sử dụng vòng lặp for gọi tệp bó thứ hai để xử lý, chuyển tệp thứ hai đó thành tên cơ sở.

Theo cho /? trợ giúp, tên cơ sở có thể được trích xuất bằng tùy chọn nifty ~ n. Vì vậy, tập lệnh cơ sở sẽ đọc:

for %%f in (*.in) do call process.cmd %%~nf

Sau đó, trong process.cmd, giả sử rằng% 0 chứa tên cơ sở và hành động tương ứng. Ví dụ:

echo The file is %0
copy %0.in %0.out
ren %0.out monkeys_are_cool.txt

Có thể có một cách tốt hơn để làm điều này trong một tập lệnh, nhưng tôi luôn có một chút mơ hồ về cách kéo nhiều lệnh trong một vòng lặp cho một tệp trong một tệp bó.

EDIT: Thật tuyệt vời! Tôi bằng cách nào đó đã bỏ lỡ trang trong các tài liệu cho thấy rằng bạn có thể thực hiện các khối nhiều dòng trong một vòng lặp FOR. Tôi sẽ phải quay lại và viết lại một số tệp bó ngay bây giờ ...


4

Mở rộng trên bài viết của Nathans . Sau đây sẽ thực hiện công việc rất nhiều trong một tập tin lô.

@echo off

if %1.==Sub. goto %2

for %%f in (*.in) do call %0 Sub action %%~nf
goto end

:action
echo The file is %3
copy %3.in %3.out
ren %3.out monkeys_are_cool.txt

:end

3

Có một công cụ thường được sử dụng trong Máy chủ MS (theo như tôi có thể nhớ) được gọi là forfiles :

Liên kết ở trên có chứa trợ giúp cũng như liên kết đến trang tải xuống microsoft.


1

Mã bên dưới lọc tên tệp bắt đầu bằng chuỗi con đã cho. Nó có thể được thay đổi để phù hợp với các nhu cầu khác nhau bằng cách thực hiện trích xuất chuỗi con và tên câu lệnh IF:

echo off
rem filter all files not starting with the prefix 'dat'
setlocal enabledelayedexpansion
FOR /R your-folder-fullpath %%F IN (*.*) DO (
set fname=%%~nF
set subfname=!fname:~0,3!
IF NOT "!subfname!" == "dat" echo "%%F"
)
pause

0

Echoing f.in và f.out sẽ tách biệt khái niệm vòng lặp nào và vòng lặp nào không được lặp khi được sử dụng trong vòng lặp for / f.

::Get the files seperated
echo f.in>files_to_pass_through.txt
echo f.out>>files_to_pass_through.txt

for /F %%a in (files_to_pass_through.txt) do (
for /R %%b in (*.*) do (
if "%%a" NEQ "%%b" (
echo %%b>>dont_pass_through_these.txt
)
)
)
::I'm assuming the base name is the whole string "f".
::If I'm right then all the files begin with "f".
::So all you have to do is display "f". right?
::But that would be too easy.
::Let's do this the right way.
for /f %%C in (dont_pass_through_these.txt)
::displays the filename and not the extention
echo %~nC
)

Mặc dù bạn không hỏi, một cách hay để truyền lệnh vào f.in và f.out sẽ là ...

for /F %%D "tokens=*" in (dont_pass_through_these.txt) do (
for /F %%E in (%%D) do (
start /wait %%E
)
)

Một liên kết đến tất cả các lệnh Windows XP: link

Tôi xin lỗi nếu tôi không trả lời đúng. Câu hỏi rất khó để tôi đọ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.