バッチファイルでワイルドカードに一致するファイルをループする方法


193

私は一連の基本ファイル名を持っています。各名前「f」には、正確に2つのファイル「f.in」と「f.out」があります。すべてのファイル名を処理するバッチファイル(Windows XPの場合)を作成します。

  • ベース名「f」を表示する
  • 「f.in」に対してアクションを実行します
  • 「f.out」に対して別のアクションを実行します

たとえば、*。in(または* .out)を検索する以外に、ベースファイル名のセットを一覧表示する方法はありません。


10
私は111/0票の後は本当にこの人になりたくありませんが、あなたの質問には再調査のwhatsoeaverは表示されません
phil294

回答:


292

2つのファイル(process_in.exeとprocess_out.exe)を処理する2つのプログラムがあるとします。

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ですか?
大佐パニック

6
@ColonelPanic- ~私の例のように、ファイル名を取得するだけのように、いくつかの修飾子があります。それが*フルパスか何かをする場合に備えてそれを使うのは私にとってただの習慣です。これらの修飾子の一握りは、(ページ下の中間)がありますmicrosoft.com/resources/documentation/windows/xp/all/proddocs/...
ジム・バック

ファイルとディレクトリにスペースがある場合はどうなりますか?
BKSpurgeon 2016

3
また、%% f変数は1文字でなければならないことに注意してください。読みやすく意味のあるものを使用しようとすると、不可解なエラーメッセージが表示されます。
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、PATHを他の有効な値に置き換えることができます。%~構文は、有効なFOR変数名によって終了されます。のように大文字の変数名を選択%Iすると、読みやすくなり、大文字と小文字を区別しない修飾子との混同が回避されます。

次のように入力すると、完全なドキュメントを取得できます FOR /?


これは機能していないようです。 %%I was unexpected at this time.
Brad

4
@Brad(バッチファイルでは%Iなく)をコマンドラインで使用している場合は、代わりに使用します%%I
doubleDown

1
受け入れられたよりもはるかに良い答え。サードパーティのウェブサイトではなく、回答に含まれるすべてのフラグ/修飾子(誰もあなたのリンクをクリックしたくない、ルイス
JustCarty

5

私が見るように、最も簡単な方法は、処理のために2番目のバッチファイルを呼び出し、その2番目のファイルにベース名を渡すforループを使用することです。

for /によると?ヘルプ、basenameはnifty〜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

1つのスクリプトでこれを行うより良い方法があるかもしれませんが、バッチファイルの単一のforループで複数のコマンドをプルする方法については、いつも少し漠然としています。

編集:それは素晴らしいです!FORループで複数行のブロックを実行できることを示すドキュメントのページをどうしても見逃していた。今から戻って、いくつかのバッチファイルを書き直さなければなりません...


4

ネイサンズの投稿を拡大しています。以下は、1つのバッチファイルでロットを実行します。

@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サーバーで通常使用しているツール(私が覚えている限り)がforfilesと呼ばれています

上記のリンクには、ヘルプとMicrosoftダウンロードページへのリンクが含まれています。


1

以下のコードは、指定された部分文字列で始まるファイル名をフィルタリングします。subfname部分文字列抽出と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をエコーすると、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
)

あなたが尋ねなかったけれども、コマンドを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.