ファイルを日付別フォルダに分類する
使おうとする度にどこ行ったっけ?ってなるのでここに貼り付けておく. 4種類あるけど、やってることは同じ. まあ、でもどれが好きって聞かれると3つ目なのかなあ.
ls | % { if (-not $_.PSIsContainer) { $dir = $_.LastWriteTime.ToString("yyyyMMdd") if (-not (Test-Path $dir)) { mkdir $dir } move-item $_ $dir } }
dir | % { if ($_.PSIsContainer) { return $null; } $dir = $_.LastWriteTime.ToString("yyyyMMdd") if (-not (Test-Path $dir)) { mkdir $dir } move-item $_ $dir }
dir | ? { -not $_.PSIsContainer } | % { $dir = $_.LastWriteTime.ToString("yyyyMMdd") if (-not (Test-Path $dir)) { mkdir $dir } move-item $_ $dir }
filter Skip-Container { if (-not $_.PSIsContainer) { return $_ } } dir | Skip-Container | % { $dir = $_.LastWriteTime.ToString("yyyyMMdd") if (-not (Test-Path $dir)) { mkdir $dir } move-item $_ $dir }
HTML メールを送信する
さりげに一番難しかったのは [System.Net.Mime.MediaTypeNames+Text]::Html だった気がするのがw
クラス内クラスはこんな書き方になるようである.
$client = new-object System.Net.Mail.SmtpClient $client.Host = "smtp.example.com" $client.Port = 25 $client.DeliveryFormat = [System.Net.Mail.SmtpDeliveryFormat]::SevenBit $message = new-object System.Net.Mail.MailMessage("From Address <foo@example.com>", "To Address <bar@example.com>") $message.Subject = "HTML mail test" $message.BodyEncoding = [System.Text.Encoding]::UTF8 $message.BodyTransferEncoding = [System.Net.Mime.TransferEncoding]::QuotedPrintable $message.Body = "plain part" $message.IsBodyHtml = $false $view = [System.Net.Mail.AlternateView]::CreateAlternateViewFromString("<b>html part</b>", [System.Text.Encoding]::UTF8, [System.Net.Mime.MediaTypeNames+Text]::Html) $view.TransferEncoding = [System.Net.Mime.TransferEncoding]::QuotedPrintable $message.AlternateViews.Add($view) $client.Send($message)
PowerShell 2 でも .NET Framework 4 を使う
PowerShell 3 からは PowerShell が .NET 4 で動作するようだけど、Windows XP は PowerShell 3 をインストール出来ないという・・・.
でも、exe.config を書けば、.NET 4 で動かせるよという話.
PS> cat $env:windir\system32\windowspowershell\v1.0\powershell.exe.config <?xml version="1.0" encoding="utf-8"?> <configuration> <startup useLegacyV2RuntimeActivationPolicy="true"> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> </startup> </configuration> PS> $PSVersionTable Name Value ---- ----- PSVersion 2.0 PSCompatibleVersions {1.0, 2.0} BuildVersion 6.0.6002.18111 PSRemotingProtocolVersion 2.1 WSManStackVersion 2.0 CLRVersion 4.0.30319.296 SerializationVersion 1.1.0.1
.NET メソッドの string 引数に null を渡す
PowerShell は $null を勝手に "" に変換して、.NET メソッドの string 引数に渡すというお節介をしてくれるので、メソッドの仕様によっては困ったことになります.
PowerShell 3 からは、そのような場合には [System.Management.Automation.Language.NullString]::Value を指定すればよくなりました.
そこで、PowerShell 2 用に同等の機能を提供するコードを書いたのが以下です.
PS> Add-Type -TypeDefinition @" >> namespace System.Management.Automation.Language >> { >> public sealed class NullString >> { >> private static volatile NullString instance; >> private static object syncRoot = new object(); >> >> private NullString() { } >> >> public static NullString Value >> { >> get >> { >> if (instance == null) >> { >> lock (syncRoot) >> { >> if (instance == null) >> instance = new NullString(); >> } >> } >> return instance; >> } >> } >> >> public override string ToString() >> { >> return null; >> } >> } >> } >> "@ >> PS> [string][System.Management.Automation.Language.NullString]::Value -eq $null True
逆FizzBuzz問題(linq)
asq を入れて、ちょっと書きなおしてみた.
order_by した後に、count して first すると empty sequence が出るという C# で出ない挙動がちょっとアレです.
from asq.initiators import query from itertools import count, cycle, islice, ifilter def FizzBuzz(): seq = [None, None, "Fizz", None, "Buzz", "Fizz", None, None, "Fizz", "Buzz", None, "Fizz", None, None, "FizzBuzz"] for i, e in enumerate(cycle(seq)): if e == None: yield i + 1 else: yield e def InverseFizzBuzz(seq): count = len(seq) def work(start): i = start c = count a = [] for x in query(FizzBuzz()).skip(start - 1): if c == 0: l = i - start return (a, l, range(start, start + l)) if not isinstance(x, int): a += [x] c -= 1 i += 1 candidates = query([3, 5, 6, 9, 10, 12, 15]).select(work).where(lambda x: x[0] == seq).to_list() if len(candidates) == 0: return None else: return query(candidates).order_by(lambda x: x[1]).first()[2] assert InverseFizzBuzz(["Fizz"]) == range(3, 4) assert InverseFizzBuzz(["Buzz"]) == range(5, 6) assert InverseFizzBuzz(["Fizz", "Buzz"]) == range(9, 11) assert InverseFizzBuzz(["Buzz", "Fizz"]) == range(5, 7) assert InverseFizzBuzz(["Fizz", "Buzz", "Fizz"]) == range(3, 7) assert InverseFizzBuzz(["Buzz", "Fizz", "Buzz"]) == None assert InverseFizzBuzz(["Fizz", "Fizz"]) == range(6, 10) assert InverseFizzBuzz(["Fizz", "Fizz", "Buzz"]) == range(6, 11)
逆FizzBuzz問題
最近ぞっぷりと linq に染まっていたので、関数の入れ子をより気持ち悪く感じて困る. python にも組み込み linq を誰か.
from itertools import count, cycle, islice, ifilter def FizzBuzz(): seq = [None, None, "Fizz", None, "Buzz", "Fizz", None, None, "Fizz", "Buzz", None, "Fizz", None, None, "FizzBuzz"] for i, e in enumerate(cycle(seq)): if e == None: yield i + 1 else: yield e def skip(itrerable, count): return islice(itrerable, count, None) def take(itrerable, count): return islice(itrerable, count) def InverseFizzBuzz(seq): def work(start, count): i = start c = count a = [] for x in skip(FizzBuzz(), start - 1): if c == 0: l = i - start return (a, l, range(start, start + l)) if not isinstance(x, int): a += [x] c -= 1 i += 1 start_list = { "Fizz": [3, 6, 9, 12], "Buzz": [5, 10], "FizzBuzz": [15] } if len(seq) == 0: return None if not (seq[0] in start_list): return None candidates = list(ifilter(lambda x: x[0] == seq, [work(i, len(seq)) for i in start_list[seq[0]]])) if len(candidates) == 0: return None else: return list(sorted(candidates, cmp = lambda x, y: x[1] - y[1]))[0][2] assert InverseFizzBuzz(["Fizz"]) == range(3, 4) assert InverseFizzBuzz(["Buzz"]) == range(5, 6) assert InverseFizzBuzz(["Fizz", "Buzz"]) == range(9, 11) assert InverseFizzBuzz(["Buzz", "Fizz"]) == range(5, 7) assert InverseFizzBuzz(["Fizz", "Buzz", "Fizz"]) == range(3, 7) assert InverseFizzBuzz(["Buzz", "Fizz", "Buzz"]) == None assert InverseFizzBuzz(["Fizz", "Fizz"]) == range(6, 10) assert InverseFizzBuzz(["Fizz", "Fizz", "Buzz"]) == range(6, 11)
追記: 無駄があった・・・
def InverseFizzBuzz(seq): def work(start, count): i = start c = count a = [] for x in skip(FizzBuzz(), start - 1): if c == 0: l = i - start return (a, l, range(start, start + l)) if not isinstance(x, int): a += [x] c -= 1 i += 1 candidates = list(ifilter(lambda x: x[0] == seq, [work(i, len(seq)) for i in [3, 5, 6, 9, 10, 12, 15]])) if len(candidates) == 0: return None else: return list(sorted(candidates, cmp = lambda x, y: x[1] - y[1]))[0][2]
CRC32
RFC 1952 - GZIP file format specification version 4.3 に載っているコードをベタ移植しただけです.
crc_table = [None] * 256 def make_crc_table(): for n in range(256): c = n for k in range(8): if c & 1: c = 0xedb88320 ^ (c >> 1) else: c >>= 1 crc_table[n] = c def update_crc(crc, s): c = crc ^ 0xffffffff if crc_table[0] == None: make_crc_table() for ch in s: c = crc_table[(c ^ ord(ch)) & 0xff] ^ (c >> 8) return c ^ 0xffffffff def crc(s): return update_crc(0, s)
RFC 2083 - PNG (Portable Network Graphics) Specification Version 1.0 だと 0xffffffff の挿入位置が微妙に違うのね(大差ないけど
crc_table = [None] * 256 def make_crc_table(): for n in range(256): c = n for k in range(8): if c & 1: c = 0xedb88320 ^ (c >> 1) else: c >>= 1 crc_table[n] = c def update_crc(c, s): if crc_table[0] == None: make_crc_table() for ch in s: c = crc_table[(c ^ ord(ch)) & 0xff] ^ (c >> 8) return c def crc(s): return update_crc(0xffffffff, s) ^ 0xffffffff