CMD窓での操作なんですが、for文の入れ子指定が
よくわからんので教えてください。
tmp+----ABCD--------file1.doc, file2.doc, etc...
|
+----1234567----ふじこ.txt, file2.csv, etc..
|
+----イロハ-------file1.doc , .htaccess, etc..
のようにtmp直下に1階層だけランダムな文字列名の
ディレクトリがあって、その中には複数のファイルが
入っているとします。
カレントはtmpにあることとし、ファイル名を
一覧化した一時作業テーブルなどは存在しません。
それらファイルを、「直上のディレクトリ名+区切り文字+元のファイル名」
(ABCD_file1.docとか)にリネームしてから、ファイルの位置をカレント
であるtmpに引き上げたいのですが…。
現時点では以下のようになっています。
for /d %%f in ( * ) do ren %%f\*.* %%f.*
for /d %%d in (.\*) do move "%%d\*" .\
これでは、まだ、一行目の(*)を後方参照して引用できて
いないので、元のファイル名の引き継ぎができません。
また、ファイル名の変更も、各ディレクトリ内の1個分に
しか適用されません。
for /D %%f in ( * ) do ( for /F ・・・と、doの直後を
入れ子にしてみたり悩んだんですが、HELPのスイッチ
説明が宇宙語で、弱っています(二晩考えたんですけど)。
/Fスイッチのusebackqオプションだろうという予感がする
のですが。
なんでvbsとかWindows PowerShellとかでなく、
いまさらdos窓なの?ってのは、特にこだわりは
ないんですが・・・いや、何となく惰性で・・・。
On Wed, 25 Jan 2012 11:10:10 -0800 (PST)
Yさ <s...@s7.wh.qit.ne.jp> wrote:
> 根本原因として、renはワイルドカード指定で使うと「拡張子を変更」する事しかできないのです。
> NG) ren %%f\*.* %%f_*.*
> OK) ren %%f\*.* *.*.%%f
!? え~・・・しらなんだ。
for /d %%d in (*) do for %%f in (%%d\*.*) do ren %%f %%d_%%~nxf
お教えの通りやってみましたら、ABCD_ABCDfile1.docとか、
二回繰り返しになりました。
# この挙動は、どうにも理解不能。
仕方なく、copyで逃げて不要になった方を削除する方法で
回避することにして、今のところ、以下のような感じです。
for /d %%d in (*) do for %%f in (%%d\*.*) do copy %%f .\%%d_%%~nxf
for /D %%D in (.\*) do rd /S /Q "%%D\"
無駄にHDDスペース使うのが、どうもトホホな感じです。
あと、フォルダ名やファイル名が半角スペース入りの場合、
動かないのも自分クオリティだな、と。
で、今日はVBS版で、カレント直上のフォルダ名を反映する
バージョンを実験中。
カレント直上のフォルダ名ってプロパティで取れるだろう
と思ったんですが、そういうの、無いのね。
で、仕方なくカレントまでのディレクトリパスを配列に入れて
\でspltして配列にしたんですが、末尾の取り方がワカラン。
かれこれ調べて、UBoundという便利な関数があることを知りました。
でも、まだ、サブディレクトリ内の*.*に対してループを
回すのがよくわからんです。
&で繋げても、狙い通りに出力されてこない。
ワイルドカード使わずに一個ずつ取っていった方が早いのかなぁ。
もすこし粘ってみて、お手上げになったらまたMLに投げます。
そのときはよろしくお願いいたしまする。 > おる
> 自分ならawk使ってファイルの一覧から「バッチファイル」を作りますね
ああ、なるほど。
linuxな人は、シェルの外部コマンドにあらかじめ存在する
前提だから、そういう発想になるわけですね。
@echo off
setlocal enableextensions
set sep="#"
rem for /f usebackq %%i in (`dir /b/ad`) do call :sub1 %%i %sep%
for /D %%i in (*.*) do call :sub1 %%i %sep%
goto :eof
:sub1:
pushd %1
for /f usebackq %%j in (`dir /b/a-d`) do copy %%j ..\%1%~2%%j
popd
goto :eof
--
木村浩一/KIMURA Koichi
I thought what I'd do was, I'd pretend I was one of those deaf-mutes
or shoud I?
mail kbk at kt.rim.or.jp
web www.kt.rim.or.jp/‾kbk/zakkicho/index.html
On Sun, 29 Jan 2012 02:10:46 +0900
KIMURA Koichi <k...@kt.rim.or.jp> wrote:
> リネーム版は読者への宿題とします
作業していた750GBのHDDを丸ごと飛ばしちゃった(!)
ので、明日以降、ゴニョります。復旧できるんか? > 自分
とりあえず、(消えても構わない)Zangband のディレクトリで
スイッチを試してみた。
C:\ztk\OmnibandTk-1.4>dir /b/ad
lib
ReadMe
tk
variant
おおおお! 不要な..とか出ないし! すげー。
C:\ztk\OmnibandTk-1.4>popd /?
PUSHD コマンドで記憶されたディレクトリに変更します。
POPD
コマンド拡張機能を有効にすると、POPD コマンドは、プッシュされている
ディレクトリ スタックからドライブを POPD するときに、PUSHD が作成した
一時的なドライブ文字を削除します。
C:\ztk\OmnibandTk-1.4>pushd /?
POPD コマンドで使用するために現在のディレクトリを保存し、
指定したディレクトリに変更します。
以下ry)
知らんスイッチや、知らんコマンドがズラズラと。
まだ全部は理解できていません。
「スタック」って言葉が出ると、もう・・・
PUSHDはSHIFTとはチト違うんですね。
2012年1月29日1:58 davi <davi...@nifty.com>:
> Yささん < こん??は でび です
...
> for /d %%d in (*) do for %%f in (%%d\*.*) do ren %%f %%d_%%~nxf
>
> お教えの通りやってみましたら、ABCD_ABCDfile1.docとか、
> 二回繰り返しになりました。
> # この挙動は、どうにも理解不能。
...
まずは、Yささんの次のバッチファイルを試してみました。
-----^
for /d %%d in (*) do for %%f in (%%d\*.*) do ren %%f %%d_%%~nxf
for /r %%f in (*) do move %%f .
-----$
私が試す限りは、でびさんが意図されたとおりに動きました。
具体的には、上記バッチファイルをmoveup.batとしてtmpディレクトリに保存して実行しました。tmpディレクトリのABCDサブフォルダにあるfile1.docが、ABCD_file1.docのファイル名にリネームされて、tmpディレクトリに移動しました。
それはともかく、僕にとっては、上記バッチの解読は、Perlのスクリプトを読むよりも難しいのですが^^;)誰か解説してもらうとありがたいぐらいです^^)/
-----^
for /d %%d in ( * ) do call :loop1 %%d
exit /b
:loop1
pushd %1
for %%f in ( * ) do call :loop2 %1 %%f
popd
exit /b
:loop2
ren %2 %1_%2
move %1_%2 ..
exit /b
-----$
バッチでもサブルーチン使えて、立派にプログラムっぽく書けるようになっているのに驚きました。
ネタ元は↓に出てくるバッチです。
.NET Frameworkのバージョンを確認する方法 - @IT
http://www.atmarkit.co.jp/fwin2k/win2ktips/246checkvdnfw/checkvdnfw.html
On Mon, 30 Jan 2012 18:07:14 +0900
JUN AMIMOTO <j...@amimo.to> wrote:
> 構造的に二重ループにした方が見通しがいいかな?と思って、こんな風に書いてみました。
ありがとうございまする。
goto でなく call で呼び出したとき、処理(なくても良いん
だろうけど、正常終了しましたよ、的な返値って言えばいい
のかな、)は、元に戻るのでしょうか。
/?にある二回終了って、スコープは取り戻せるよ、というような
意味のように思えるのですが、その理解にも自信がありません。
私は、お示し頂いたコードを、1つめのfor 文で1個目の
ファイルを読み込んでから、2つめのfor 文(loop1)に放流し、
そのまま3つめのloop2に処理をぶん投げて放流。あとは知らん。
ワシは既に2個目の処理に移っておるワイ・・・という風に、
蛙の歌輪唱方式のコードだと理解したのですが、その解釈で
当たっていますか?
バッチはMS-DOS 3.3Dの頃にやりこんだ気もしますが、なにしろ
前世紀のことですので、すっかり忘れています。
その頃はcommand /c とか書かないと取り戻せなかったような・・・
という程度のうっすらとした記憶しかありません。
そこで、ご負担にならない範囲で、ちと解説をお願いしたいです。
ーーーーーーーーーーーー
官報見ていたら、
JISでプログラム言語Fortranー第3部:条件付き翻訳 X3001ー3
電子計算機プログラム言語Ada X3009
プログラム言語Prologー第1部:基本部
が廃止されたようですね。
http://kanpou.npb.go.jp/20120120/20120120g00013/20120120g000130024f.html
制定された日本工業規格
地理情報`地理マーク付け言語(GML)X7136
廃止された日本工業規格
地理情報ー地理空間データ交換用XML符号化法 X7199
http://kanpou.npb.go.jp/20120125/20120125h05724/20120125h057240009f.html
On Sun, 29 Jan 2012 15:40:55 +0900
jscripter <jscri...@gmail.com> wrote:
> 上記バッチファイルをmoveup.batとしてtmpディレクトリに保存して実行
私は拡張子cmdで保存しました。
いろいろ書き換えたときに%の個数間違えたのかなぁ。
もしかして、batだと問答無用でcommand.comが
呼ばれる仕様なのですかね…。
> Perlのスクリプトを読むよりも難しい
どっちもどっちのような・・・。
下のバッチを試してみてください。
以前はこういうの書こうとすると、別にサブのバッチが必要でしたが
今は :ラベル を CALL 出来るようになったので、1つのバッチで書けます。
「自分自身をCALLして指定ラベルに制御を移す」という動作のようです。
だから /B オプション付きの EXIT で戻ってこれる、と。
おかげで見通しのいいバッチが書きやすくなりました。
自分の場合、普段使いでちょこちょこっとなんか書くのはいまだにPerlが多いですが
「自分の環境以外でも動くもの」を作る場合、wsh も多いですが、ちょっとしたものはバッチ書くこともまだまだ多いです。
-----^
@echo off
echo 行くよ。
call :step1
echo 元に戻ったよ。
goto :EOF
:step1
echo 来たよ。
call :step2
echo 戻ったよ。
exit /b
:step2
echo また来たよ。
exit /b
-----$
.cmdという拡張子の存在自体が記憶の彼方でした^^;) NT系と9x系の違いですか・・・
2012年1月30日23:10 davi <davi...@nifty.com>:
2012年1月30日18:07 JUN AMIMOTO <j...@amimo.to>:
On Tue, 31 Jan 2012 01:48:13 +0900
JUN AMIMOTO <j...@amimo.to> wrote:
> 戻りますよ。
> 「自分自身をCALLして指定ラベルに制御を移す」という動作のようです。
> だから /B オプション付きの EXIT で戻ってこれる、と。
おほ~。vbaのsub()~end subと同じですね!
いつの間にこんな事に…。
> 「自分の環境以外でも動くもの」を作る場合、wsh も多いですが、
> ちょっとしたものはバッチ書くこともまだまだ多いです。
Enterprise版のVISTAや7が導入されていて、ユーザに、
ホントに非adminなユーザ権限しかない環境(当然、
Windows PowerShellの使用権限もナシ。)で、ちょっとした
ことをできるようにするために配布するものって、どうすれば
良いでしょう?
「vistaのエレベータ」というソフトでは、少なくとも一度は
adminのパスワードを借りなければだめなようですし。
vbsもwshもbatも昇格権限がかかってストップしてしまう
場合が結構あって、弱っています。
たとえばリダイレクトが絡むフィルタ系の外部コマンドを
動かそうとした場合など。
MSの資料漁ったら、証明書付きexe以外に、手書きでxml形式の
マニフェストを作ってexeと同じディレクトリに置けばうまく
ゆく場合もあるらしい記述を先週、やっと見つけたのですが、
なんだかかったるい。
ここ二年ほど、ずっと困っています。
コマンドラインツール用のバーチャルマシンとかを探すと
良いのかなぁ。
ーーーーーーーーーーーーーー
寒気と乾気でのどをやられました。
換気には気をつけていたんですが。頭、痛ぇ。
皆さんもお気をつけて!
TSNETスクリプト通信第15号の記事の一つに本スレッドのバッチを取りまとめたいのですがいかがでしょうか。
よろしくご検討ください。今日、Yささんにimagineというawkスクリプトゲームの記事を投稿していただいたのですが、私のこれから書く記事^^;)と合わせて、2つしかありませんので・・・取り込みたし^^)/
2012年2月1日2:19 davi <davi...@nifty.com>:
On Wed, 1 Feb 2012 21:46:40 +0900
"jscripter" <jscri...@gmail.com> wrote:
> 合わせて、2つしかありませんので・・・取り込みたし^^)/
お任せいたしまする。
理解が届いていない部分がまだ多いので、入門者向けの
解説記事風にまとめてくださると有り難いです。
機械伯爵さん、でびさんの投稿とムムリクさんの羊蹄山と雲海の写真の投稿とずいぶん充実した第15号になりそうです。
バッチについてはもう少し自分でも理解するためのまとめをしたいと思います。
風邪は早く直してくださいね。
2012年2月2日0:22 davi <davi...@nifty.com>:
・「call :ラベル」という構文
・「exit /b」という構文
・「pushd / popd」という構文
・move.exe コマンド
てなあたりでしょうかね。
「call :ラベル」という構文は「自分自身をCALLして指定ラベルに制御を移す」という動作、
「exit /b」という構文は、「CMD.EXE ではなく、現在のバッチスクリプトを終了」ということなので、
結果として「:ラベル~exit /b」間をサブルーチン・コール出来る、ということでしょう。
CALL /? の文言は冗長で難解ですが、「CALL :ラベル
は、実際にはサブルーチン・コールではなく、別のバッチ・コンテキストを生成するので、CALL先から元のバッチ自体を終了させるためには、2回「終了」しなければいけない」という意味なんでしょうね、きっと。
#しかし CALL /? は読みごたえ満点!ですな。ははは。
あと、「exit /b」はたぶん「goto :EOF」と等価なんでしょうけど、「goto :EOF」は美しくないと感じるので「exit
/b」の方が好きですね。明解だし。
2012年2月2日21:45 JUN AMIMOTO <j...@amimo.to>:
> あと、フォルダ名やファイル名が半角スペース入りの場合、
> 動かないのも自分クオリティだな、と。
いろいろ調べたのですが、意外と手強いというか、バッチコマンドの仕樣が大変わかりにくいですね。
確かに、半角スペース入りのファイル名のファイルがYささんやaMIさんのバッチでは移動できないです。
木村さんのバッチでも動かないなあ・・・
なんだか、よくわからんという感じになってきました^^;)
半角空白を含むファイル名でも動くようにするには、
-----^
for /d %%d in (*) do for %%f in (%%d\*.*) do ren "%%f" %%d_%%~nxf
for /r %%f in (*) do move "%%f" .
-----$
とすればよいですね。コマンドの引数の%%fを""で括っています。
-----^
for /d %%d in (*) do for %%f in (%%d\*.*) do ren "%%f" "%%d_%%~nxf"
for /r %%f in (*) do move "%%f" .
-----$
%%d_%%~nxfも""で括ります。
半角空白ファイル名を取り扱えるようにするには、やはり、コマンドの引数の%%fを""で括るとよいですね。
ディレクトリも同様なのだろうと思われます。
ディレクトリ名に半角空白を含む場合は、次のようにして正解。""で括るのは文字列として展開される変数部分。代入される変数は括る必要はない。
-----^
for /d %%d in (*) do for %%f in ("%%d\*.*") do ren "%%f" "%%d_%%~nxf"
for /r %%f in (*) do move "%%f" .
コマンド拡張機能の有効化
レジストリのHKEY_LOCAL_MACHINE→ Software→ Microsoft→ Command
Processorとキーの値「EnableExtensions」が1で有効になる。デフォルトで1になっている。
1. コマンド拡張機能を有効にすると、callのターゲットとしてラベルが使えるようになる。
call :ラベル 引数
2. 以下のforコマンドも拡張機能を有効にする必要がある。
for /d %変数 in (セット) do コマンド [コマンドパラメータ]
セットがワイルドカードを含む場合は、ファイル名ではなくディレクトリ名
の一致を指定します。
for /r [[ドライブ:]パス] %変数 in (セット) do コマンド [コマンドパラメータ]
[ドライブ:]パスから始めて、ツリーの各ディレクトリで for 文を実行し
ます。/r の後にディレクトリが指定されていない場合は、現在の
ディレクトリが使用されます。セットが単一のピリオド (.) である場合は、
ディレクトリ ツリーの列挙だけを行います。
3. setlocalはcmd.exeで拡張機能を利用かどうかを判断するために使える
VERIFY OTHER 2>nul
SETLOCAL ENABLEEXTENSIONS
IF ERRORLEVEL 1 echo 拡張機能を有効にできません
この方法が使えるのは、古いバージョンの CMD.EXE では、SETLOCAL は
ERRORLEVEL の値を設定しないためです。VERIFY コマンドに誤った引数を
指定すると、ERRORLEVEL の値は 0 以外の値に初期化されます。
On Sat, 4 Feb 2012 19:15:59 +0900
"jscripter" <jscri...@gmail.com> wrote:
> > ディレクトリも同様なのだろうと思われます。
>
> ディレクトリ名に半角空白を含む場合は、次のようにして正解。
> ""で括るのは文字列として展開される変数部分。
> 代入される変数は括る必要はない。
ここのカンが働かなかったです。inの直前も
括って「おかしいなぁ。括るだけではだめなんか。」とか
「展開後に"が一つ残るようにエスケープのエスケープ
みたいにしないとだめなんだろうか」とか。
で、頭が、ワヤワヤになって放り投げていました。
記事にまとめると宣言するまではよかったのですが、Webでいろいろ調べてもあまりよくわからない。トライ・アンド・エラーでやっていると本当にもういいよみたいな感じになってしまいますね。
理屈がそれほどあるわけではなくて、仕様ですからね。コマンドのヘルプも非常にわかりにくい。Perlの経験から類推して、合理的にはこうなっているんだろうみたいなところです。
2012年2月5日7:07 davi <davi...@nifty.com>: