วิธีวนซ้ำไฟล์ที่ตรงกับ wildcard ในแบตช์ไฟล์


194

ฉันมีชุดชื่อไฟล์ฐานสำหรับแต่ละชื่อ 'f' มีสองไฟล์คือ 'f.in' และ 'f.out' ฉันต้องการเขียนไฟล์แบตช์ (ใน Windows XP) ซึ่งผ่านชื่อไฟล์ทั้งหมดสำหรับแต่ละไฟล์ควร:

  • แสดงชื่อฐาน 'f'
  • ดำเนินการกับ 'f.in'
  • ดำเนินการอื่นกับ "f.out"

ฉันไม่มีวิธีใด ๆ ในการแสดงรายการชุดของชื่อไฟล์พื้นฐานนอกเหนือจากการค้นหา * .in (หรือ * .out)


10
ฉันไม่ต้องการเป็นผู้ชายคนนี้หลังจากการโหวต 111/01 แต่คำถามของคุณไม่แสดงการค้นพบใหม่ใด ๆ ที่นักสะสม
phil294

คำตอบ:


293

สมมติว่าคุณมีสองโปรแกรมที่ประมวลผลไฟล์สองไฟล์คือ process_in.exe และ process_out.exe:

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

%% ~ nf เป็นตัวดัดแปลงการทดแทนที่ขยาย% f เป็นชื่อไฟล์เท่านั้น ดูโมดิฟายเออร์อื่น ๆ ในhttps://technet.microsoft.com/en-us/library/bb490909.aspx (ตรงกลางหน้ากระดาษ) หรือเพียงแค่ตอบคำถามต่อไป


47
ใช้ '%' หนึ่งตัวหากพิมพ์บนบรรทัดคำสั่ง ฉันรู้ว่า OP ไม่ได้ถามเกี่ยวกับบรรทัดคำสั่ง แต่นั่นคือสิ่งที่ฉันค้นหาเมื่อคำถามนี้ปรากฏขึ้นที่ด้านบนของการค้นหา Google ของฉัน คนอื่นอาจชื่นชมสิ่งนี้
Jason

2
คุณช่วยอธิบายไวยากรณ์ได้ไหม? มีการประกาศตัวแปรลูป%%fทำไมจึงเป็น%%~nfภายหลัง
พันเอก Panic

6
@ColonelPanic - มี~ตัวดัดแปลงจำนวนหนึ่งในการทำสิ่งต่าง ๆ เช่นในตัวอย่างของฉันเพียงแค่รับชื่อไฟล์ มันเป็นนิสัยสำหรับฉันที่จะใช้มันในกรณีที่*ทำเส้นทางแบบเต็มหรือบางสิ่งบางอย่าง มีตัวดัดแปลงจำนวนหนึ่ง (อยู่ตรงกลางหน้า): microsoft.com/resources/documentation/windows/xp/all/proddocs/ …
Jim Buck

เกิดอะไรขึ้นถ้าไฟล์และไดเรกทอรีมีช่องว่างในพวกเขา?
BKSpurgeon

3
นอกจากนี้โปรดทราบว่าตัวแปร %% f จะต้องเป็นตัวอักษรเดียว - ข้อความแสดงข้อผิดพลาดที่เป็นความลับจะปรากฏขึ้นหากคุณพยายามใช้สิ่งที่อ่านได้และมีความหมาย
Bruce Dawson

90

คุณสามารถใช้บรรทัดนี้เพื่อพิมพ์เนื้อหาของเดสก์ท็อปของคุณ:

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

เมื่อคุณมี%%Iตัวแปรมันเป็นเรื่องง่ายที่จะดำเนินการคำสั่งกับมัน (เพียงแทนที่คำ echo ด้วยโปรแกรมของคุณ)

นอกจากนี้การแทนที่การอ้างอิงตัวแปร FOR ได้รับการปรับปรุงตอนนี้คุณสามารถใช้ไวยากรณ์เพิ่มเติมดังต่อไปนี้:

%~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

ในตัวอย่างข้างต้น%Iและเส้นทางสามารถถูกแทนที่ด้วยค่าที่ถูกต้องอื่น ๆ %~ไวยากรณ์ถูกยกเลิกโดยใช้ชื่อตัวแปรที่ถูกต้อง การเลือกชื่อตัวแปรตัวพิมพ์ใหญ่เช่น%Iทำให้อ่านง่ายขึ้นและหลีกเลี่ยงความสับสนกับโมดิฟายเออร์ซึ่งไม่คำนึงถึงขนาดตัวพิมพ์

คุณสามารถขอรับเอกสารฉบับเต็มได้โดยพิมพ์ FOR /?


ดูเหมือนจะใช้งานไม่ได้ %%I was unexpected at this time.
แบรด

4
@Brad หากคุณกำลังใช้สิ่งนี้ในบรรทัดคำสั่ง (และไม่ได้อยู่ในไฟล์แบทช์) ให้ใช้%Iแทน%%I
doubleDown

1
คำตอบที่ดีกว่าที่ยอมรับ ธง / ตัวดัดแปลงทั้งหมดรวมอยู่ในคำตอบและไม่ใช่เว็บไซต์ของบุคคลที่สาม ( ไม่มีใครต้องการคลิกลิงก์ของคุณ, Louis )
JustCarty

5

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

ตามสำหรับ /? ช่วยให้สามารถแยก basename โดยใช้ตัวเลือกที่ดี ~ n ดังนั้นสคริปต์ฐานจะอ่าน:

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

จากนั้นใน process.cmd ให้ถือว่า% 0 มีชื่อฐานและดำเนินการตามนั้น ตัวอย่างเช่น:

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

อาจมีวิธีที่ดีกว่าในการทำเช่นนี้ในสคริปต์เดียว แต่ฉันมักจะสับสนเล็กน้อยเกี่ยวกับวิธีการดึงคำสั่งหลายคำสั่งในหนึ่งเดียวสำหรับลูปในไฟล์แบตช์

แก้ไข: นั่นวิเศษมาก! ฉันพลาดหน้าในเอกสารที่แสดงว่าคุณสามารถบล็อกหลายบรรทัดในวงวน FOR ได้ ฉันจะต้องกลับไปและเขียนไฟล์แบตช์ใหม่ตอนนี้ ...


4

การขยายโพสต์Nathans ต่อไปนี้จะทำงานมากในไฟล์แบตช์เดียว

@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

มีเครื่องมือที่มักใช้ใน MS Servers (เท่าที่ฉันจำได้) เรียกว่าforfiles :

ลิงค์ด้านบนมีวิธีใช้และลิงค์ไปยังหน้าดาวน์โหลดของ Microsoft


1

รหัสด้านล่างกรองชื่อไฟล์เริ่มต้นด้วยสตริงย่อยที่กำหนด มันสามารถเปลี่ยนแปลงได้เพื่อให้เหมาะกับความต้องการที่แตกต่างกันโดยทำงานกับการแยกซับสตริงย่อยและคำสั่ง 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

การสะท้อน f.in และ f.out จะแยกแนวคิดของสิ่งที่จะวนซ้ำและสิ่งที่ไม่ต้องวนซ้ำเมื่อใช้ในการสำหรับ / 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
)

แม้ว่าคุณจะไม่ได้ถามวิธีที่ดีในการส่งคำสั่งไปยัง f.in และ f.out ก็คือ ...

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

ลิงค์ไปยังคำสั่ง Windows XP ทั้งหมด: ลิงค์

ฉันขอโทษถ้าฉันไม่ตอบคำถามนี้อย่างถูกต้อง คำถามยากมากสำหรับฉันที่จะอ่าน

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