コマンドプロンプトのワンライナーでズンドコキヨシ
cmd.exeでもやります。期待してましたよね?よね?
概要
最近流行の「ズンドコキヨシ問題」を、コマンドプロンプト(cmd.exe)のワンライナーで解いてみました。
Javaの講義、試験が「自作関数を作り記述しなさい」って問題だったから
— てくも (@kumiromilk) 2016年3月9日
「ズン」「ドコ」のいずれかをランダムで出力し続けて「ズン」「ズン」「ズン」「ズン」「ドコ」の配列が出たら「キ・ヨ・シ!」って出力した後終了って関数作ったら満点で単位貰ってた
解
cmd /v:on /c "for /L %i in (1,1,1000) do @call set /a a5=a4,a4=a3,a3=a2,a2=a1,a1=^%RANDOM^% % 2 >nul & set A=!a5!!a4!!a3!!a2!!a1!& if !a1!==1 (echo ズン) else (echo ドコ) & if !A!==11110 echo キ・ヨ・シ! & exit"
雑な解説
- 処理を途中で終了する必要があるため、cmdコマンドでサブプロセスを起動する。
- /v:on は遅延環境変数を有効にするオプション
- /c "文字列" は、文字列に渡されたコマンドを実行するオプション
- ※詳細は→コマンドプロンプトで読んでおくべき7つのHELP - その①「cmd /?」 - くんすとの備忘録
- 0か1をランダムに1000回出力
- ※この部分ね→for /L %i in (1,1,1000) do @call set /a a1=^%RANDOM^% % 2
- 1のときは「ズン」0のときは「ドコ」を割り当て
- 初期値が「0」になるので、逆にすると初回に「ドコ」が出たら終了しちゃう
- 0か1だったという履歴(A)を5回まで保持(a1~a5)しておく。
- 履歴(A)が「11110」のとき、つまり「ズン ズン ズン ズン ドコ」だった時、「キ・ヨ・シ!」を出力して子プロセスを終了する
【2015年度版】コマンドプロンプトのワンライナーでFizzBuzz
これは、コマンドプロンプト(cmd.exe) Advent Calendar 2015 - Qiitaの25日目、最終日の記事です。
※Windows 10 Home 64bit 搭載のcmd.exeにて検証を行っています。
さて、これまでのFizzBuzz
ということで、2015年の脳みそでもう一度書いてみました。
for /L %i in (1 1 20) do @set /a a=%i%15,b=%i%5,c=%i%3>nul&if !a!==0 (echo FizzBuzz) else (if !b!==0 (echo Buzz) else (if !c!==0 (echo Fizz) else echo %i))
155バイト。2014年版とほとんど変わりませんね。
かなりシンプルで見やすいですし、わりと完成形かもしれません。
まとめ
コマンドプロンプト(cmd.exe) Advent Calendar 2015 - Qiita、見事に完走しました!
記事を書いてくださった、@k0hARCHさん、@ryoana14さん、@nmrmsysさん、ありがとうございました!!
それではみなさま良いお年を!!!!
うちのPCのプロビジョニング用BAT
これは、コマンドプロンプト(cmd.exe) Advent Calendar 2015 - Qiitaの23日目の記事です。
※Windows 10 Home 64bit 搭載のcmd.exeにて検証を行っています。
さて、うちのメインマシンはLinuxでもMac OS XでもなくWindowsなんですが、数ヶ月に1回くらいのペースで再インストールしたくなるので、それに合わせて環境構築用のBATファイルを常用しています。
構成
ざっくり、以下のような構成です。
セットアップ
ファイルサーバ上で実行し、諸々をインストールする
- Installer
- Software-ZIP
同期
フォルダごと端末へコピーし、その上でジャンクションを張ったりする
- profile
- Roaming
- usr
- Git-repos
- work
セットアップ
Installer
これは、chocolateyのためのパッケージ一覧と、インストーラのexe、そしてそれらを動かすプロビジョニング用BATで構成されています。
- #pckage.config (chocolateyのためのパッケージ一覧)
<?xml version="1.0" encoding="utf-8"?> <packages> <package id="lhaplus" /> <package id="git" /> <package id="google-chrome-x64 " /> <package id="firefox" /> <package id="flashplayerplugin" /> <package id="skype" /> <package id="line" /> <package id="mpc-hc" /> <package id="evernote" /> <package id="atom" /> <package id="imagemagick" /> <package id="paint.net" /> <package id="inkscape" /> <package id="gimp" /> <package id="audacity" /> </packages>
- ###SETUP_by_ROOT.bat (プロビジョニング用BAT)
@echo off pushd "%~dp0" SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin echo. echo --- Chocolateyによるインストール --- @where choco if errorlevel 1 powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" cinst -y "#packages.config" echo. echo --- 自動・手動インストール --- for %%i in ( "teraterm-4.86.exe /SILENT /LOADINF=teraterm.inf" SourceTreeSetup_1.6.14.exe TeamFileSet64-2.1.143.2013.exe GoogleJapaneseInputSetup.exe wlsetup-web.exe msys2-i686-20150916.exe LplsShlx64-v1.0.1.0\install.cmd ) do ( echo "%%~i" start /w "%%~i" %%~i ) pause
管理者でBATファイルを殴ると、Chocolateyによるインストールが実施され、その後同じフォルダ内にある指定されたインストーラが順番に起動します。インストーラはちょいちょい手作業が必要です。
手動の作業が混ざっていて悲しいですね。
Software-ZIP
これは、インストールしなくても使用できるソフトウェアのZIPファイルと、それらを解凍するプロビジョニング用BATで構成されています。
- ####SETUP_by_USER.bat (プロビジョニング用BAT)
@echo off pushd "%~dp0" set DESTDIR=C:\Software set LOGFILE=%DESTDIR%\log.txt SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\tools REM make directory if not exist %DESTDIR% mkdir %DESTDIR% for /f "usebackq tokens=*" %%i in (`dir /b *.zip`) do ( if not exist "%DESTDIR%\%%~ni" ( echo 7za x "%%~i" -o"%DESTDIR%\" 7za x "%%~i" -o"%DESTDIR%\" >> "%LOGFILE%" echo. ) ) pause
一般ユーザでBATファイルを殴ると、C:\Software にディレクトリを作成し、同じフォルダ内にある全てのZIPファイルをそこに解凍してくれます。
こっちは全自動です。
同期
profile
ここには %USERPROFILE% 以下のフォルダが格納されており、プロビジョニング用BATでジャンクションを作成します。
- #SETUP_by_USER.bat
@echo off set ROOT=%~dp0. set BKUPDIR=●init.%DATE:/=% cd /d %USERPROFILE% if not exist %BKUPDIR% mkdir %BKUPDIR% @echo on @for /f "usebackq tokens=*" %%a in (`dir /b /ad %ROOT%`) do ( move %%a %BKUPDIR%\ mklink /j %%a %ROOT%\%%a ) pause
Roaming
ここには %USERPROFILE%\AppData\Roaming 以下のフォルダが格納されており、プロビジョニング用BATでジャンクションを作成します。
- #SETUP_by_USER.bat
@echo off set ROOT=%~dp0. set BKUPDIR=●init.%DATE:/=% cd /d %USERPROFILE%\AppData\Roaming if not exist %BKUPDIR% mkdir %BKUPDIR% @echo on @for /f "usebackq tokens=*" %%a in (`dir /b /ad %ROOT%`) do ( if exist "%%~a" move "%%~a" %BKUPDIR%\ mklink /j "%%~a" "%ROOT%\%%a" ) pause
usr
プロビジョニング用BATで、C:\usr からこのBATのあるフォルダへのジャンクションを作成します。
※ついでに環境変数の設定も行います
- #SETUP_by_USER.bat
@echo off set SRC=%~dp0 set DEST=C:\usr if exist %DEST% ( echo %DEST% はすでに存在します pause exit ) @echo on mklink /j %DEST% %SRC% setx ROOT C:\usr setx HOME %ROOT%\home setx PATH "%PATH%;%ROOT%\lnk;%ROOT%\bin" pause
work
プロビジョニング用BATで、C:\work からこのBATのあるフォルダへのジャンクションを作成します。
- #SETUP_by_USER.bat
@echo off set ROOT=%~dp0 cd /d C:\ if exist work ( echo C:\work はすでに存在します pause exit ) @echo on mklink /j work %ROOT% pause
Git-repos
ここには C:\Git-repos (Gitリポジトリ置き場) 以下にgit cloneしたいリポジトリのリストが置かれており、プロビジョニング用BATでgit cloneします。
- list.txt
git@github.com:kunst1080/AnubisGG.git kunst1080/AnubisGG git@github.com:kunst1080/BatLibrary.git kunst1080/BatLibrary git@bitbucket.org:kunst1080/musics.git kunst1080/musics git@github.com:kunst1080/vm-install-freebsd.git kunst1080/vm-install-freebsd git@bitbucket.org:tsukiusagi_pj/lych.git tsukiusagi_pj/lych https://github.com/playframework/playframework.git playframework/playframework https://github.com/hakobera/nvmw.git hakobera/nvmw https://github.com/usp-engineers-community/Open-usp-Tukubai.git usp-engineers-community/Open-usp-Tukubai
※git cloneするURLと、出力先(相対パス)をスペースで区切ったリストです
- #SETUP_by_USER.bat
@echo off set LIST=%~dp0list.txt set DESTDIR=C:\Git-repos set GIT="C:\Program Files (x86)\Git\bin\git.exe" REM make directory if not exist %DESTDIR% mkdir %DESTDIR% REM Git clone cd /d %DESTDIR% for /f "usebackq tokens=1,2" %%a in (`type "%LIST%"`) do ( echo git clone %%a %%b %GIT% clone %%a %%b echo. ) pause
※スクショのある場所とない場所がありますが、お察しください。
D&Dされたファイルにタイムスタンプを付けてバックアップするBATファイル
これは、コマンドプロンプト(cmd.exe) Advent Calendar 2015 - Qiitaの22日目の記事です。
※Windows 10 Home 64bit 搭載のcmd.exeにて検証を行っています。
ちょっとしたバックアップ取得用にBATファイルを使っています。
まずはソース
Archive_FLAT.bat
@echo off REM 場所 set ARC_PATH=%CD%\●ARCHIVE rem タイムスタンプ set dt=%DATE:/=% set tm=%TIME: =0% set tm=%tm::=% set tm=%tm:~0,6% set TIMESTAMP=%dt%%tm% rem 結局、ファイルを移動するのかコピーするのか? set COMMAND=%~1 SHIFT IF NOT EXIST "%ARC_PATH%" MKDIR "%ARC_PATH%" IF "%~1"=="" ( explorer "%ARC_PATH%" goto :eof ) REM コピー処理 REM ループする。 :COPY_LOOP rem ファイル名 set FILE_NAME=%TIMESTAMP%_%~nx1% REM 確定フルパス set TARGET=%ARC_PATH%\%FILE_NAME% %COMMAND% "%~1" "%TARGET%" shift if not "%~1"=="" goto :COPY_LOOP goto :EOF
もしくは
Archive_DIR.bat
@echo off REM 場所 set ARC_PATH=%CD%\●ARCHIVE\%DATE:/=% rem タイムスタンプ set dt=%DATE:/=% set tm=%TIME: =0% set tm=%tm::=% set tm=%tm:~0,6% set TIMESTAMP=%dt%%tm% rem 結局、ファイルを移動するのかコピーするのか? set COMMAND=%~1 SHIFT IF NOT EXIST "%ARC_PATH%" MKDIR "%ARC_PATH%" IF "%~1"=="" ( explorer "%ARC_PATH%" goto :eof ) REM コピー処理 REM ループする。 :COPY_LOOP rem ファイル名 set FILE_NAME=%TIMESTAMP%_%~nx1% REM 確定フルパス set TARGET=%ARC_PATH%\%FILE_NAME% %COMMAND% "%~1" "%TARGET%" shift if not "%~1"=="" goto :COPY_LOOP goto :EOF
ざっくりした機能
いずれも、D&Dされたファイルの先頭にタイムスタンプ文字列を付与して、バックアップフォルダ「●ARCHIVE」へ移動orコピーします。
「Archive_FLAT.bat」はそのまま、「Archive_DIR.bat」は今日の日付でサブディレクトリを作成しその中へバックアップされます。
使い方
どちらも、使いたい場所にショートカットを作成して使用します。
- 「リンク先」の第一引数に、「MOVE」もしくは「COPY」を追記します。
- 「MOVE」の場合は移動、「COPY」の場合はコピーされます。
- 「作業フォルダー」に、バックアップフォルダを作成する場所を指定します。空白にすると、ショートカットの置いてある場所になります。
こんな感じで。
BATファイルでuniqコマンドを実装
これは、コマンドプロンプト(cmd.exe) Advent Calendar 2015 - Qiitaの21日目の記事です。
※Windows 10 Home 64bit 搭載のcmd.exeにて検証を行っています。
BATファイルを使って簡易版uniqコマンドを作成します。
uniq.bat
@echo off for /f "usebackq tokens=* delims=" %%i in (`findstr .*`) do call :sub %%i goto :EOF :sub if not "%PREV%"=="%*" ( set PREV=%* echo %* ) exit /b
標準入力の1行1行をサブルーチンに渡し、サブルーチン内で「ひとつ前の行の値」を保持しているだけ、という単純な作りです。
使用例
入力ファイル (aaa.txt)
aaa bbb ccc ccc cccccc bbb
実行
C:\usr\home>type aaa.txt | uniq aaa bbb ccc cccccc bbb C:\usr\home>type aaa.txt | sort | uniq aaa bbb ccc cccccc
いじょ。
BATファイルで、ロックファイルを使った排他制御を行う
これは、コマンドプロンプト(cmd.exe) Advent Calendar 2015 - Qiitaの20日目の記事です。
19日目は @nmrmsys さんの "Tee for ToeKick 実行コマンドラインまで含めてログファイルに出力するコマンド" でした。
残りは全部自分です。最後まで駆け抜けるよ!
※Windows 10 Home 64bit 搭載のcmd.exeにて検証を行っています。
さてさて
今回はBATファイルにおける排他制御に関して書きますが、自分がやったことのある内容で、ということで、もうちょい範囲を限定します。
今回は「2つのBATファイルの実行について、ロックファイルを使った排他制御を行う」という内容で書きます。
挙動について
「処理1.BAT」と「処理2.BAT」の実行を排他制御します。
- 「処理1.BAT」が起動した直後に「処理2.BAT」が起動すると「処理2.BAT」は待ち状態になり、「処理1.BAT」が終了すると「処理2.BAT」が動き出す
- 「処理2.BAT」が起動した直後に「処理1.BAT」が起動すると「処理1.BAT」は待ち状態になり、「処理2.BAT」が終了すると「処理1.BAT」が動き出す
- 「処理1.BAT」と「処理2.BAT」が同時に起動した場合、「処理1.BAT」が優先される
書きました
※検証しやすいように両方共最後にpauseを入れていますがお気になさらず
処理1.BAT
@echo off set LOCK_PREFIX=lock set LOCK_FILE=%LOCK_PREFIX%.proc1 rem チェック前にロックファイルを作成する copy nul > %LOCK_FILE% :CHECK echo ロックファイルのチェック(%~n0) rem 自分のロックファイルのみの場合、ERRORLEVEL=1 rem 他人のロックファイルが存在する場合、ERRORLEVEL=0 dir /b %LOCK_PREFIX%.* | findstr -v %LOCK_FILE% > nul if %errorlevel%==0 timeout /t 2 > nul & goto :CHECK :MAIN echo 時間のかかる何らかの処理 開始 timeout /t 5 > nul echo 時間のかかる何らかの処理 終了 echo. :END del %LOCK_FILE% pause
処理2.BAT
@echo off set LOCK_PREFIX=lock set LOCK_FILE=%LOCK_PREFIX%.proc2 :CHECK echo ロックファイルのチェック(%~n0) rem 誰かのロックファイルが存在する場合、ERRORLEVEL=1 dir /b %LOCK_PREFIX%.* > nul 2>&1 if %errorlevel%==0 timeout /t 2 > nul & goto :CHECK rem チェック後にロックファイルを作成する copy nul > %LOCK_FILE% :MAIN echo 時間のかかる何らかの処理 開始 timeout /t 5 > nul echo 時間のかかる何らかの処理 終了 echo. :END del %LOCK_FILE% pause
簡単ですが、こんな感じで。
私見ですが、2つの処理の排他制御を完全に同じ形にするとかち合う可能性があるように思うので、上記でやったように、優先度をつけて微妙に異なる実装にする方が気が楽です。
Windows10のビルトインアプリの削除方法と戻し手順
いらないアプリ、いっぱいありますよね。消しましょう。
削除方法
不要アプリ削除.bat
※管理者権限で起動しましょう
@echo off for %%i in ( 3dbuilder windowsalarms windowscommunicationsapps photos windowscamera soundrecorder officehub skypeapp getstarted windowsmaps onenote people windowsphone solitairecollection zunemusic zunevideo xboxapp bingfinance bingsports ) do ( powershell -NoProfile -ExecutionPolicy Unrestricted -Command "Get-AppxPackage *%%i*" | findstr "^Name" powershell -NoProfile -ExecutionPolicy Unrestricted -Command "Get-AppxPackage *%%i* | Remove-AppxPackage" ) pause
戻し手順
全部戻す場合
powershellを管理者で開いて
Get-AppxPackage -AllUsers| Foreach {Add-AppxPackage -DisableDevelopmentMode -Register "$($_.InstallLocation)\AppXManifest.xml"}
個別に戻す場合
OneNoteをインストールする
powershellを管理者で開いて
Get-AppxPackage -Name "Microsoft.Office.OneNote" -AllUsers | Foreach {Add-AppxPackage -DisableDevelopmentMode -Register "$($_.InstallLocation)\AppXManifest.xml"}