Cara loop melalui file yang cocok dengan wildcard dalam file batch

193

Saya memiliki satu set nama file dasar, untuk setiap nama 'f' sebenarnya ada dua file, 'f.in' dan 'f.out'. Saya ingin menulis file batch (di Windows XP) yang melewati semua nama file, untuk masing-masing harus:

  • Tampilkan nama dasar 'f'
  • Lakukan tindakan pada 'f.in'
  • Lakukan tindakan lain di 'f.out'

Saya tidak punya cara untuk membuat daftar nama file dasar, selain mencari * .in (atau * .out) misalnya.

Luke Halliwell
sumber
10
Saya benar-benar tidak ingin menjadi orang ini setelah 111/01 suara, tetapi pertanyaan Anda tidak menunjukkan penelitian apa pun
phil294

Jawaban:

292

Dengan asumsi Anda memiliki dua program yang memproses dua file, process_in.exe dan process_out.exe:

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

%% ~ nf adalah pengubah substitusi, yang memperluas% f menjadi nama file saja. Lihat pengubah lain di https://technet.microsoft.com/en-us/library/bb490909.aspx (di tengah halaman) atau hanya di jawaban berikutnya.

Jim Buck
sumber
47
Gunakan '%' tunggal jika mengetik ini di baris perintah. Saya tahu OP tidak bertanya tentang baris perintah, tetapi itulah yang saya cari ketika pertanyaan ini muncul di bagian atas pencarian Google saya. Orang lain mungkin menghargai bagian ini.
Jason
2
Bisakah Anda menjelaskan sintaksisnya? Variabel loop dideklarasikan %%fmengapa %%~nfnanti?
Kolonel Panic
6
@ ColonelPanic - ada beberapa ~pengubah untuk melakukan hal-hal, seperti dalam contoh saya, dapatkan nama file. Ini hanya kebiasaan bagi saya untuk menggunakannya kalau-kalau *jalan penuh atau sesuatu. Ada beberapa pengubah ini (di tengah halaman): microsoft.com/resources/documentation/windows/xp/all/proddocs/…
Jim Buck
bagaimana jika file dan direktori memiliki spasi di dalamnya?
BKSpurgeon
3
Perlu diketahui juga bahwa variabel %% f harus berupa satu huruf - pesan kesalahan samar akan muncul jika Anda mencoba menggunakan sesuatu yang dapat dibaca dan bermakna.
Bruce Dawson
90

Anda dapat menggunakan baris ini untuk mencetak konten desktop Anda:

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

Setelah Anda memiliki %%Ivariabel, Anda dapat melakukan perintah dengan mudah (cukup ganti kata echo dengan program Anda)

Selain itu, substitusi referensi variabel UNTUK telah ditingkatkan Anda sekarang dapat menggunakan sintaks opsional berikut:

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

Dalam contoh di atas %Idan PATH dapat diganti dengan nilai-nilai valid lainnya. The %~sintaks diakhiri dengan nama variabel UNTUK valid. Memilih nama variabel huruf besar suka %Imembuatnya lebih mudah dibaca dan menghindari kebingungan dengan pengubah, yang tidak peka huruf besar-kecil.

Anda bisa mendapatkan dokumentasi lengkap dengan mengetik FOR /?

Tandai Ingram
sumber
Ini sepertinya tidak berhasil. %%I was unexpected at this time.
Brad
4
@Brad jika Anda menggunakan ini di command-line (dan bukan dalam file batch), kemudian gunakan %Isebagai gantinya%%I
doubleDown
1
Jawaban yang jauh lebih baik daripada yang diterima. Semua bendera / pengubah termasuk dalam jawaban dan bukan situs web pihak ketiga ( tidak ada yang ingin mengklik tautan Anda, Louis )
JustCarty
5

Cara termudah, seperti yang saya lihat, adalah dengan menggunakan loop untuk yang memanggil file batch kedua untuk diproses, melewati file kedua itu nama dasar.

Menurut untuk /? bantuan, nama bas dapat diekstraksi menggunakan opsi bagus ~ n. Jadi, skrip dasarnya akan berbunyi:

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

Kemudian, dalam process.cmd, asumsikan bahwa% 0 berisi nama dasar dan bertindak sesuai dengannya. Sebagai contoh:

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

Mungkin ada cara yang lebih baik untuk melakukan ini dalam satu skrip, tapi saya selalu agak kabur tentang cara menarik beberapa perintah dalam satu untuk loop dalam file batch.

EDIT: Itu luar biasa! Saya entah bagaimana melewatkan halaman di dokumen yang menunjukkan bahwa Anda dapat melakukan blok multi-baris dalam loop FOR. Saya akan harus kembali dan menulis ulang beberapa file batch sekarang ...

Nathan Fritz
sumber
4

Memperluas pada posting Nathans . Berikut ini akan melakukan banyak pekerjaan dalam satu file batch.

@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
Martin
sumber
3

Ada alat yang biasanya digunakan dalam Server MS (sejauh yang saya ingat) disebut forfiles :

Tautan di atas berisi bantuan serta tautan ke halaman unduhan microsoft.


sumber
1

Kode di bawah ini memfilter nama file yang dimulai dengan substring yang diberikan. Itu dapat diubah agar sesuai dengan kebutuhan yang berbeda dengan bekerja pada ekstraksi subfname dan pernyataan 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
Sandro Rosa
sumber
0

Echoing f.in dan f.out akan memisahkan konsep apa yang harus loop dan apa yang tidak untuk loop ketika digunakan dalam for / f loop.

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

Meskipun Anda tidak bertanya, cara yang baik untuk mengirimkan perintah ke f.in dan f.out adalah dengan ...

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

Tautan ke semua perintah Windows XP: tautan

Saya minta maaf jika saya tidak menjawab ini dengan benar. Pertanyaan itu sangat sulit bagi saya untuk dibaca.

Z. Mickaels
sumber