指定以外のファイルやフォルダを削除したい。(デスクトップで指定した複数ファイル以外のファイルを一括削除する)

Okwave(教えてgoo!)からの質問。すでに No.4 で回答済み。

質問者:moon879 指定以外のファイルやフォルダを削除したい。

困っています デスクトップ上にあるファイル、フォルダの内、
指定したファイル、フォルダ以外を削除するBATファイル、
もしくはVBSを作成したいのですが、
どのような記述をすれば良いのでしょうか?
OSはWindows2000 server SP4です。

どなたかご教示よろしくお願いいたします。

例:
デスクトップに以下の2つのファイルと1つのフォルダがあり、
これ以上デスクトップにファイルやフォルダを増やしたくないのですが、

「hoge2.txt」
hoge.lnk」
hoge

誤って以下のファイルとフォルダを作成してしまいました。

「hoge1.txt」
hoge.jpg」
「hoge2」


「hoge2.txt」と「hoge.lnk」「hoge」は常にデスクトップに残し、
「hoge1.txt」と「hoge.jpg」「hoge2」を一括削除したい。

質問投稿日時:09/03/28 03:48質問番号:4832987

http://okwave.jp/qa4832987.html

以下のような流れでバッチを作成しました。
(1)pushd でデスクトップに移動。
(2)デスクトップの全てのファイルに対してfor文でサブルーチンへ飛ぶ。
(3)デスクトップの全てのフォルダに対してfor /D 文でサブルーチンへ飛ぶ.

for %%f in ( * ) do call :sub "%%f"

という記述は常套手段でよく使います。全てのファイルに対してやりたい処理を :sub 以降に記述します。

サブルーチンでは
(1)flag 変数をOFFにセット
(2)for 文で残したいファイル・フォルダ名のファイルセットを指定してサブルーチンで指定した引数(=デスクトップ上のファイル・フォルダ名)を名前を比較して、一致したらflagをONにセット
(3)flag がONなら何もせずサブルーチンを終了
(4)ファイルだったら、指定された引数に対してdelコマンドを実行
(5)フォルダだったら、指定された引数に対してrd /S /Qコマンドを実行
という流れです。

サブルーチンについては、call /? のヘルプに説明があります。

:---------------------------------------------------- sample.bat
echo off
pushd %userprofile%\デスクトップ
for %%f in ( * ) do call :sub "%%f"
for /D %%f in ( * ) do call :sub "%%f" d
popd
exit /b

:sub
set flag=OFF
for %%e in ( hoge2.txt hoge.lnk hoge ) do if %1=="%%e" set flag=ON
if "%flag%"=="ON" goto :EOF
if "%2"=="" del %1
if "%2"=="d" rd /S /Q %1
goto :EOF

良回答20pt頂きました。ありがとうございます!

バッチファイルで配列を使う(環境変数を使って配列変数風に使う)方法について

このはてなダイアリーでは自動的に各エントリーの下にリンク元が表示されます。簡易的なアクセスログみたいなもんですが、最近「バッチファイル 配列」というキーワードで見に来ている人が多いことが判明しました。

つまり、バッチファイルで配列変数を使いたい、使い方を知りたいということですね。

結論から言うと、配列変数そのものはバッチファイルにはありません。
しかし配列変数風のものを作って使うことはできます。

まずは配列変数を実現している風に見えるサンプルから。

手っ取り早く、配列変数風のものを使ったサンプルをお見せします。

:--------------------------------------------sample.bat
echo off
for /L %%i in (1,1,10) do set x[%%i]=%%i

echo x[1]=%x[1]%
echo x[8]=%x[8]%
echo.
set x
echo.
set p=4
call echo call echo の場合 --- x[4]=%%x[%p%]%%
for /L %%i in (1,1,10) do (
   call echo %%x[%%i]%%
)

setlocal ENABLEDELAYEDEXPANSION
echo setlocalの場合 --- x[4]=!x[%p%]!
for /L %%i in (1,1,10) do (
   echo !x[%%i]!
)
echo.
set sum=0

for /L %%i in (1,1,10) do (
   if %%i == 5 call set ans5=%%x[%%i]%%
   if %%i == 7 set ans7=!x[%%i]!
   call set /a sum = sum + %%x[%%i]%%
)

echo ans5=%ans5%
echo ans7=%ans7%
echo sum=%sum%


何となく判ってきましたか?
要は、“変数名[数字]”という環境変数名を使っているだけです。そう、"[" 数字 "]"は添え字ではなくあくまで環境変数名の一部です。

配列変数風の配列的な使い方って?

なぜ配列を使いたいかというと、配列というのは添え字の中の数値を変数にして、ループしたり参照したりしたいわけです。
普通の言語の感覚でしたら、添え字の中を変数にしてもそのまま

echo x[i]

と表示したり、

set a=x[i]

という風に代入したりできますよね(この場合iが変数)。バッチは環境変数を%i%という風に"%"でくくって参照するので、同じように考えて

echo %x[%i%]%

set a=%x[%i%]%

などと書いて上手く動かなくて悩むわけです。
じゃあどう書けばいいか。以下にまとめます。

配列変数風書き方のまとめ

(添え字に使う環境変数をiとします。あらかじめ set i=1 などが実行されている。)


■添え字の数値が固定の場合 〜 つまりこれはただの環境変数です。
配列への代入     set x[1]=sample
配列の表示      echo %x[1]%
配列を他の変数へ代入 set ans=%x[1]%


■添え字に変数を使いたい場合 〜 call echo , call set を使う場合
配列への代入     set x[%i%]=sample
配列の表示      call echo %%x[%i%]%%
配列を他の変数へ代入 call set ans=%%x[%i%]%%

どういう理屈か説明しますと、
(1)call echo %%x[%i%]%% の行が評価される。%%→%、%i%→1(環境変数iの中身)に置き換えられる。
(2)call echo %x[1]% としてcall文が実行され組み込みコマンドのechoが子プロセスで実行される(らしい)。
(3)結果として、echo %x[1]% という行が評価されて、環境変数x[1]の中身が表示される。
ということになります。


■添え字に変数を使いたい場合 〜 setlocal ENABLEDELAYEDEXPANSION を使う場合
あらかじめバッチの先頭(途中でも良い)で
setlocal ENABLEDELAYEDEXPANSION
と宣言しておきます。その後以下のように記述します。

配列への代入     set x[%i%]=sample
配列の表示      echo !x[%i%]!
配列を他の変数へ代入 set ans=!x[%i%]!

以上まとめ終わり。

call set,call echo を使うか、setlocal ENABLEDELAYEDEXPANSIONを使うかは好みで決めてください:-)

余談

 添え字の中に使う環境変数の中身は数値である必要はありません。文字列でもかまいません。なぜなら数字であろうと文字列であろうと環境変数名の一部だからです。上手く使えば連想配列のように使えます。
 また、添え字の"[" "]"が無くてもかまいません。区切りをわかりやすくするために使っているだけです。使わないと特にcall set 〜を使った時に"%%x%i%%%"などと%が続いてわかりにくいでしょう(参考エントリ→Yahoo!知恵袋(バッチファイルで反復処理) バッチで配列変数のような添え字を環境変数で使う - バッチもん研究所 blog)。

わかんなかったら、コメント欄でご質問ください。質問大歓迎!

ファイル名を特定の文字までを削除したい(ファイル名の先頭から最初に見つかった特定の文字までを削除する)

OKWave から。ファイル名の先頭から特定の文字までを削除したい、フリーソフトを探していますという相談。フリーソフトではなくバッチで考えてみました。

質問者:xykatakaak ファイル名を特定の文字までを削除したい

「23564_abcdef_1a2b3c」というような「_」で繋いだ文字列のファイル名を、最初の「_」までを、その「_」自身も含めて削除したいのです。
最初の「_」までの文字の数はまちまちで、かなりの数のファイルを処理したいのです。

このようなリネームが出来るフリーソフトはあるでしょうか?(シェアウェアでもかまわないのですが)

http://okwave.jp/qa4763716.html

シェアウェアどころかバッチでできちゃいます。シェアウェアに払ったつもりでかわりにおごってください ;-P


以下が先頭から"_"までを取り除くバッチです。


"_"が入っていないファイル名、"_"が最後にあるファイル名は無視します(何もしない)。
"_"が連続する場合やフィアル名の途中に"."が複数ある様な特殊な場合は考慮していません(ややこしいので)。

このバッチを処理したいファイルのあるフォルダに置いて実行します。
ここでは対象はフォルダ内の全ファイルですが、例えばテキストファイルだけにしたければ2行目の
for /F "delims=" %%f in ('dir /b') do call :sub "%%f"

for /F "delims=" %%f in ('dir /b *.txt') do call :sub "%%f"
という風に変えればOKです。

:--------------------------------------------------- loop.bat
echo off
for /F "delims=" %%f in ('dir /b') do call :sub "%%f"
exit /b

:sub
set fname=%~1
set n=0

:loop
   call set c=%%fname:~%n%,1%%
   set /a n=n+1
   if "%c%"=="" goto :EOF
   if "%c%"=="_"  goto break
goto loop
:break
call set newname=%%fname:~%n%%%
if "%newname%"=="" goto :EOF
if "%newname:~0,1%"=="." goto :EOF
ren "%fname%" "%newname%"
goto :EOF

一文字ずつ順番に比較する地道なバッチです。
call set c=%%fname:~%n%,1%%
のところで、部分文字列の指定に変数を使うための小細工をしています。
昔だったら一時ファイルを作っていただろうなぁ。

SendTo ここでコマンドプロンプトを開く を実現するバッチ

Tweak UI に同じような機能があるようなのですがSendToフォルダに入れておくと、

 フォルダを選んで右クリック→送る→CMD_here.bat

で指定したフォルダをカレントディレクトリにしてコマンドプロンプトを開くバッチです。

フォルダの代わりに

 ファイルを選んで→送る→CMD_here.bat

とした場合は、そのファイルの存在するフォルダをカレントディレクトリにしてコマンドプロンプトを開きます。

残念ながらフォルダのショートカットではうまく動いてくれません(ショートカットのあるフォルダが開く)。

:--------------------------------------- CMD_here.bat
@echo off
for %%d in (%1) do set x=%%~ad
if "%x:~0,1%"=="d" (pushd "%~dpn1") else (pushd "%~dp1")
cmd /k

置き場所は、C:\Documents and Settings\(ユーザ名)\SendTo です。
置き場所が見つけられない人は、コマンドプロンプト

start "" "%userprofile%\SendTo"

と入力すれば置き場所のフォルダが開きます。

Yahoo!知恵袋(バッチファイルで反復処理) バッチで配列変数のような添え字を環境変数で使う

またまた、Yahoo!知恵袋での質問にこちらで勝手に答えちゃいます。

バッチファイルで反復処理mario_kinopioさん

バッチファイルで反復処理

バッチファイル(.bat)で複数の環境変数に対して反復処理をさせたいです。
例えばJavaで複数の処理対象にに対して反復処理をする場合、配列を作って

String[] tmp = {"Morning", "Afternoon", "Evening"};
Srting sum="";
for(int i ; i<=3 ; i++){
sum=sum+tmp[i];
}

などとするのが定石だと思うのですが、これをバッチファイルでやりたい時、
set bat1=Morning
set bat2=Afternoon
set bat3=Evening
と定義してfor文かif分+LOOPで回そうとしてもうまくいきません。

うまくいかない例その1
set /a N=1
:LOOP
set bat=%bat%N%% ←%bat*%の変数名をむりやり作ろうとしている:失敗
if "%N%"=="3" (goto EXIT)
set /a N=N+1
goto LOOP
:EXIT

うまくいかない例その2
set /a N=1
:LOOP
set bat0=bat%N% ←bat0に処理対象の変数名を入れる
if defined %bat0% (echo "○")
set bat=%bat%%%bat0%% ←bat0の保持データを変数名として使おうとしている:失敗
if "%N%"=="3" (goto EXIT)
set /a N=N+1
goto LOOP
:EXIT

バッチファイルはかじっている程度で手探りしながら作っているのですが、
万策尽きた感じです。どなたか助言等をお願いします。
XP SP3環境下でのコマンドプロンプトを使ったバッチファイルに関しての回答のみでお願いします。

http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1421854949

(うまくいかない例その1のような)%環境変数%の入れ子は通常のsetではできません。全くできないかというと、call set 〜 を使うと出来ます。他に環境変数の遅延展開や一旦別のバッチファイルを作成してそれを呼び出す方法(例:「バッチで前日の日付を求める」bat内の「月跨り処理」の所)があります。

で、今回はcall set 〜を使ってXPで動作確認したバッチファイルの例です。

set bat1=Morning
set bat2=Afternoon
set bat3=Evening
set /a N=1
:LOOP
  call set bat=%bat%%%bat%N%%%
  if "%N%"=="3" (goto EXIT)
  set /a N=N+1
goto LOOP
:EXIT

このブログを見てくれないかなぁ。

漢数字で九九の表を出力するバッチファイル(どう書く?orgの課題)

Webサイトを巡っていておもしろいサイトを発見。

screenshot

どう書く?org」へようこそ!このサイトは出されたお題をいかに解くか競い合う、プログラマのためのコロシアムです。投稿を試してみたい方はテスト、とりあえず眺めてみたい方は言語の一覧 がおすすめです。


ここに興味ある課題が。
漢数字で九九表を出力するプログラムを作るのだが、条件としてプログラムソース中でアラビア数字を使えないという課題だ。

漢数字で九九の表

漢数字で九九の表 syat #7820(2008/10/23 07:42 GMT) [ Other ] 評価7/7=1.00

漢数字で九九の表を作ってください。
ただし以下の条件をつけます。

条件
一.アラビア数字(0〜9)禁止。
  プログラムにも出力結果にもアラビア数字を含んではいけない。(全角・半角とも)
二.結果の数字は、「七」とか「一○」(=10)とか「六四」(=64)のような形式とする。
三.九九の結果をそのままプログラム中に書き込んではいけない。


出力例

 一  二  三  ・・・・
 二  四  六  ・・・・
 三  六  九  ・・・・
 四  八 一二
 ・
 ・

http://ja.doukaku.org/212/

いろんな言語でチャレンジしている人がいる。まぁ、普通の言語だと文字列操作の関数とか列挙型などが充実しているから作り易いだろうと思いつつ、こうなるとどうしてもバッチファイルで作りたくなる。

バッチファイル中でアラビア数字を使わないとなると、%1などの引数も使えないので call :sub 形式は無理だなぁと漠然と思う。まずはとにかく0〜10の数値を変数に入れる手段を考えた。

考えついたのがfor文のファイルセットに対する%変数からファイルサイズを求める%~z変数の記述を使うこと。

次に、ファイルサイズが0バイト〜10バイトのファイルを作る方法。
0バイトのファイルを作るのは、type NUL>filename でよく知られている。
2バイトのファイルは echo.>filename で改行(CRLF)の2バイトのファイルができあがる。
問題は1バイトのファイルを作る方法。いろいろ試行錯誤した結果、

type nul>〇
copy /a 〇 一>NUL

とすると0バイトのファイル"〇"に対して Ctrl-Z が付加された"一"というファイルができあがることが判った。
3〜10バイトのファイルを作るのはecho 文で簡単にできる。

次に九九なので順当にfor文の二重ループ。
括弧を使った複合文は嫌いなのだが、call :sub 形式が使えないのでしようがない。九九の計算はfor文でファイルセットに〇 一 二 … 九 をならべてそのファイルサイズ %%~zx , %%~zy を使えば数値を取り出せると目星をつけた。
あとは、10の位と1の位に分けるために、%十% という固定値を使う。これはあらかじめファイルサイズから環境変数"十"に数値を代入したものを使うことにした。
最後に10の位と1の位にわけた数値を漢数字に戻す。ここでもfor文のファイルセットとファイルサイズを比較して一致したファイル名=漢数字となることを利用した。ここで!a!や!b!という環境変数の遅延展開を使った(遅延展開の記述は嫌いなんだが)。
最後は段毎に整形して終わり。
できたバッチファイルはこれ。

echo off
setlocal ENABLEDELAYEDEXPANSION

type nul>〇
copy /a 〇 一>NUL
echo.>二
echo ->三
echo -->四
echo --->五
echo ---->六
echo ----->七
echo ------>八
echo ------->九
echo -------->十

for %%i in (十) do set %%i=%%~zi

for %%x in (一 二 三 四 五 六 七 八 九) do (
   for %%y in (一 二 三 四 五 六 七 八 九) do (
      set /a a= %%~zx * %%~zy  /  %十%
      set /a b= %%~zx * %%~zy  %% %十%
      set ans_a= 
      for %%i in (一 二 三 四 五 六 七 八)       do if !a! EQU %%~zi set ans_a=%%i
      for %%i in (〇 一 二 三 四 五 六 七 八 九) do if !b! EQU %%~zi set ans_b=%%i
      set line=!line! !ans_a!!ans_b!
    )
    echo !line! & set line=
)

for %%i in (〇 一 二 三 四 五 六 七 八 九 十) do del %%i

この後見直して、数値→漢数字への変換部分は call set 〜を使えば環境変数の副文字列(部分文字列)を取り出すことができると気がついた。これなら総当たりのループが不要になる。
そのバージョンのバッチファイルは以下のようになった。

echo off
setlocal ENABLEDELAYEDEXPANSION

type nul>〇
copy /a 〇 一>NUL
echo.>二
echo ->三
echo -->四
echo --->五
echo ---->六
echo ----->七
echo ------>八
echo ------->九
echo -------->十

set str=〇一二三四五六七八九

for %%i in (一 十) do set %%i=%%~zi

for %%x in (一 二 三 四 五 六 七 八 九) do (
   for %%y in (一 二 三 四 五 六 七 八 九) do (
      set /a a= %%~zx * %%~zy  /  %十%
      set /a b= %%~zx * %%~zy  %% %十%
      call set ans_a=%%str:~!a!,%一%%%
      call set ans_b=%%str:~!b!,%一%%%
      set ans_a=!ans_a:〇= !
      set line=!line! !ans_a!!ans_b!
    )
    echo !line! & set line=
)

for %%i in (〇 一 二 三 四 五 六 七 八 九 十) do del %%i

ソースの見た目は最初に作った方が好きだけれど、速度的にはこちらのほうが早いようだ。


更にもう他に改良の余地はないかと考えてみた。
数値を変数に入れるのに、以前 set コマンドで設定されている変数が使えないかと眺めていたことを思い出してもう一度見てみると、NUMBER_OF_PROCESSORSというのがある。以前も気づいていたのだが、「プロセッサの数だったら環境によって1だったり2だったりするよなぁ」とそこで思考停止していた。よく考えたら割り算すればこの変数から数値の1が作れる!数値の1から他の数値は計算で求められるなと気づいて、ファイルサイズではなく環境変数の数値を使うバージョンのバッチファイルを作ってみた。
ここではループもファイルサイズではなく変数の数値を使うので for /L を使っている。

echo off
setlocal ENABLEDELAYEDEXPANSION

set /a 一= NUMBER_OF_PROCESSORS / NUMBER_OF_PROCESSORS
set /a 九= (一 + 一 + 一) * (一 + 一 + 一)
set /a 十= 九 + 一 

set str=〇一二三四五六七八九

for /L %%x in (%一%,%一%,%九%) do (
   for /L %%y in (%一%,%一%,%九%) do (
      set /a a= %%x * %%y  /  %十%
      set /a b= %%x * %%y  %% %十%
      call set ans_a=%%str:~!a!,%一%%%
      call set ans_b=%%str:~!b!,%一%%%
      set ans_a=!ans_a:〇= !
      set line=!line! !ans_a!!ans_b!
    )
    echo !line! & set line=
)

このバッチファイルはファイルを作らない分更に早いようだ。だいぶ短くなった。

だが個人的にはやはり最初に作ったあやしげなバージョンが好きである。数値を求めるために漢数字ファイル名のファイルを作るという馬鹿馬鹿しさ。これこそパチもんなバッチファイルだと思う。

startコマンドは結構色々なものを解釈してくれる。

Yahoo!知恵袋からの質問からまたまた引用。

コマンドプロンプトでヤフーを開くのはどのようにコマンドを入力すればいいのです...satoshi8280306さん

コマンドプロンプトでヤフーを開くのはどのようにコマンドを入力すればいいのですか????

http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1321786718

start コマンドを使います。

start http://www.yahoo.co.jp/

ほかにも

start hoge.txt

start sample.xls

など、関連付けを解釈してプログラムを起動してくれます。
拡張子の関連付けがされている場合は start コマンドが不要で、ファイル名だけ記述してもソフトが起動します。

hoge.txt  → メモ帳で hoge.txt が立ち上がる

sample.xls → sample.xls が開く


ファイル名などをダブルクォーテーションでくくる場合は

start "" "c:\Program Files\Internet Explorer\iexplore.exe"

という風に先頭に "" をつけます。この部分はタイトル指定になるため。start /? に説明があります。