PowerShell -Part 4
■ このスレッドは過去ログ倉庫に格納されています
>>610 >New-Item -type HardLink -Name linktest\hardlink -Target linktest\target 5.1と7.0.3で試したけどエラーにならなかったぞ これでどう? (長すぎて切れるかも) $origCurDir = [System.Environment]::CurrentDirectory New-Item -ItemType Directory -Path linktest Push-Location linktest New-Item -ItemType Directory -Path dir Push-Location dir # linktest/dir New-Item -ItemType Directory -Path subdir Set-Content -Path file -Value "hello" New-Item -ItemType HardLink -Path hardlink_1 -Value file New-Item -ItemType SymbolicLink -Path symlink_1 -Value subdir Pop-Location # linktest New-Item -ItemType HardLink -Path dir/hardlink_2 -Value dir/file New-Item -ItemType SymbolicLink -Path dir/symlink_2 -Value subdir Push-Location dir # linktest/dir [System.Environment]::CurrentDirectory = $PWD New-Item -ItemType HardLink -Path hardlink_3 -Value file New-Item -ItemType SymbolicLink -Path symlink_3 -Value subdir Pop-Location # linktest [System.Environment]::CurrentDirectory = $PWD New-Item -ItemType HardLink -Path dir/hardlink_4 -Value dir/file New-Item -ItemType SymbolicLink -Path dir/symlink_4 -Value subdir Pop-Location [System.Environment]::CurrentDirectory = $origCurDir Get-ChildItem -Path linktest/dir | Sort-Object -Property CreationTime | Format-Table Attributes,LinkType,Target,Length,Name >>613 これを思い出した ******** アメリカのNASAは、宇宙飛行士を最初に宇宙に送り込んだとき、 無重力状態ではボールペンで文字を書くことができないのを発見した。 これではボールペンを持って行っても役に立たない! NASAの科学者たちはこの問題に立ち向かうべく、10年の歳月と120億ドルの開発費をかけて研究を重ねた。 その結果ついに、無重力でも上下逆にしても水の中でも氷点下でも摂氏300度でも、 どんな状況下でもどんな表面にでも書けるボールペンを開発した!! 一方、ソ連は鉛筆を使った。 リンクを張ることが目的なのではない PowerShellの不具合を見つけることが目的なのだ 誰か英語ができる人 >>612 のテストを添えて「New-Itemでのhardlink/symlink作成に [Environment]::CurrentDirectoryが影響する」ってタイトルでイシューを立てて欲しい 昔はよくConnectに投稿したりしたんだけどねぇ バージョン上がって使いやすくなってきたねpowershell Shellより扱いやすいからmacにもインスコしたわ コンソールに貼り付けて実行した時に右クリックの貼り付けとctlvの貼り付けで動きが違うのは何で? 遅レスすまんね >>597 だめだった >>598 見てみる あるファイルを消そうとしたら「このファイルは開かれているため〜」と表示されて消せなかった。 こういう場合、自分はリソースモニターでファイルを開いているアプリを探すんだけど 最近入った現場では管理者以外はリソースモニターを使えないように設定されていて困った。 それで質問なのですが、powershellのコマンドでファイルを開いているアプリを探す方法はあるのでしょうか? >>622 めっちゃ参考になります。っていうかこれでやります。 サンクス! 試せば判るけど >>622 はプロセスがロードしてるDLLとかのモジュールしか得られないよ 開いてるファイルはプロセスに紐付いてるハンドル取得して一個一個チェックするしかないよ 実装はpowershellじゃかなり大変だからhandle.exeっていうMSが公開してるツール使ったらいいよ セキュリティガチガチでネットにも繋がらないうちの現場じゃ無理だな うちの会社は「キッコーマン」のHPが見れません、”コーマン”がフィルターに引っかかるのですw openfiles コマンドでファイルを開いているプロセスを調べる 【 Windows】 http://tooljp.com/windows/doc/Server2008/openfiles/openfiles.html Openfiles https://web.archive.org/web/20120424081342/http ://technet.microsoft.com/ja-jp/library/cc772842(v=ws.10).aspx 職場で「さすがパワーシェラー!」って言われたんだけど パワーシェルを使う人のことをそう呼ぶものなの? 洋書で良い本ないですか? 和書だと数冊しか出てないので… in actionは読んだのかね あとはCoreのソース読んでくのが手っ取り早い >>631 原書は第3版まで出てるんですね ありがとうございます 多次元配列(ジャグ配列ではなく)を1次元配列に平坦化する高速な方法ありませんか? データ数は100万個くらいです。 @($a | % {$_}) 検索したら↑のカッコいい方法が出てきましたが、 私の環境で6秒ほどかかり速度に不満があります。 パイプとForeach-Object自体が遅いからね データがオンメモリにあるならforeach文のが速い あとは万個の繰り返し処理になるわけだからpowershellで書いたら全体的には当然遅い 対策としては繰り返し部分だけC#に渡すとかだね foreach文にすると0.8秒まで速くなりました! とりあえずこの方法でやってみます $b = foreach($x in $a){$x} >>636 美人穴が「この商品は累計○万個も売り上げたということです!」とかいうとおっきする >>633 >多次元配列(ジャグ配列ではなく)を1次元配列に平坦化する高速な方法ありませんか? なんでジャグ配列ではなく多次元配列なんだろう 多次元配列のほうがメモリ上で綺麗に配置されている分、高速化の選択肢が多いかもしれないって発想じゃね >>639 ExcelファイルからCOM経由で範囲データを取ってくるとobject[,]になるためです PowerShellというか.NETの仕様 .NETには1次元配列の要素にアクセスするための専用命令があるので速い 多次元配列の要素にアクセスするにはプロパティみたいなアクセサメソッドを使わなきゃいけないので遅い >>646 多次元だと倍以上遅いと言う根拠あるの? 要は根拠もなしに > 実際には多次元配列の方が遅い と妄想をほざいてただけって話かよw >>651 うん、良いんじゃね、そういう結論で。 以上でよろしいか? >>ID:l+r11Fp5 たくさん構ってもらえて良かったね >>643 Excelファイルから取得したデータを更に別の処理に使うのですが、その際に1次元で渡す必要があるためです 実装としては添え字でメモリの位置を計算して参照するだけだから 一次元でも多次元でも原理的には速さは変わらないぞ >>656 きみが絶対的に正しいことはスレ住人の総意で共通認識なのだから、もう十分だろう? そのへんで勘弁してもらないかな。なんなら土下座して謝るよ。 ちゃんとアンカー追えよ ジャグ配列vs多次元配列が1次元vs多次元配列に化けてるぞ >>647 >多次元だと倍以上遅いと言う根拠あるの? 「倍以上遅い」なんてどこから来たんだろう >>658 >>646 によると専用命令があるらしいけど、嘘なのかね? >>660 ああすまん、脳内で二次元配列 ⇔ ジャグ配列 って思ってたわ まあ3次元以上なら専用命令とやらがもっと速くないとダメだけど http://www5b.biglobe.ne.jp/ ~yone-ken/VBNET/IL/il15_UseArray.html > ILにも1次元配列については専用の命令が用意されています。 #2次元配列初期化 Measure-Command { $i = 0; $array = New-Object "object[,]" 1000,1000 for ($x = 0; $x -lt $array.GetLength(0); $x++) { for ($y = 0; $y -lt $array.GetLength(1); $y++) { $array[$x,$y] = $i++ } } } #ジャグ配列初期化 Measure-Command { $i = 0; $array = New-Object "object[]" 1000 for ($x = 0; $x -lt $array.length; $x++) { $array[$x] = New-Object "object[]" 1000 for ($y = 0; $y -lt $array[$x].length; $y++) { $array[$x][$y] = $i++ } } } たしかに初期化の段階でジャグ配列のが速いね >>662 ジャグ配列知らんの? 二次元相当のジャグ配列だと2回辿らないとダメだから倍は速くないとトータルで遅くなるでしょ 軽くググったら最近の.Net Coreとかだと状況次第って感じやね https://takap-tech.com/entry/2020/02/24/213932 原理考えたらまあ妥当な結果だと思う 処理系の実装に寄るけど、うまくインデックスを張れば 速度的には同等になるはずだけどな >>671 どういう理論なんだ? ランダムアクセスだとジャグ配列は次元毎にメモリーアクセスして辿らないとダメだけど多次元配列ならインデックスの計算してその場所にアクセスするだけだから多次元配列の方が速い シーケンシャルアクセスだとアクセスの多くは最後の次元のアクセスだから毎回インデックスを計算する多次元配列よりジャグ配列の方が速いと思う まあめっちゃ最適化して多次元配列を1次元配列に展開するようなコードにまで落とせたら多次元配列の方が微妙に速くなるかも なんにせよ多次元配列を1次元配列に高速に平坦化する方法分からないんだろ グダグダスレ引き延ばしておきながらなw @($a) Foreach-Objectもforeach分も要らない >>673 そんな低レベルなことでドヤれるとか羨ましいわw >>674 >@($a) PSってこんなオチが多いね $aって打てば全部列挙されて出てくるんだからあれれとは思うんだけどさ >>674 返信遅れてすみません。 0.2秒まで速くなりました。 シンプルかつナンバーワンですね 目からウロコでした。 >>677 こういうトリッキー系?は趣味PGならいいんだけど 業務PGに実装するには躊躇するんだよなあw PowerShell使うならほぼ常識、てか知らないと辛いレベル そもそもPowerShell自体が色々トリッキーな動作するし、特に配列周り $a = [Object[,]]::new(3,3); $a.Rank は 2 $b = $a; $b.Rank は 2 $b = & { $a }; $b.Rank だと 1 $b = $a + @(); $b.Rank でも 1 もちろん $b.Length はどれも 9 $b = $a が特例のように思えてきた どうしてこうなるのかきちんと理屈が知りたい 配列での foreach の使用 (C# プログラミング ガイド) https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/arrays/using-foreach-with-arrays 多次元配列の場合、右端の次元のインデックスが最初に加算されていき、次にその左の次元、またその左、というような方法で各要素がトラバースされます。 int[,] numbers2D = new int[3, 2] { { 9, 99 }, { 3, 33 }, { 5, 55 } }; // Or use the short form: // int[,] numbers2D = { { 9, 99 }, { 3, 33 }, { 5, 55 } }; foreach (int i in numbers2D) { System.Console.Write("{0} ", i); } // Output: 9 99 3 33 5 55 明示的な foreach の使用は興味がないなあ $b = $a も $b = & { $a } も $a を $b に代入するのに なんで結果が違うのかが知りたい 最初のやつ以外はシンプルな代入じゃなくて演算してるから、演算の結果が一次元配列になっただけじゃないの $b = & { $a } も演算? 具体的にどういう演算になるのかわからない >>682 >$b = & { $a }; $b.Rank だと 1 >$b = $a + @(); $b.Rank でも 1 この2つは$aがそれぞれ評価されて1次元になって$bに代入されてる $b = & { $a } の場合$aの前にカンマを入れれば型は保たれる $b = & { ,$a } PowerShellの謎仕様 おそらくスクリプトブロックを通過するときと 右辺や左辺に置いて演算するとき それぞれ1次元に変換されてしまう仕様みたい >>686 起動演算子にスクリプトブロックを渡してるんだから演算でしょ スクリプトで $a とだけ書くと$aが評価されて左上から順に9行分の出力が得られる $b=&{$a}はその出力の代入になってる じゃあやっぱり単純な代入 $b = $a だけが特別で それ以外は配列が展開されるってことか 理解した >>687 & { $a } だと配列 $a が展開される & { ,$a } にすれば配列の配列 ,$a が展開されて配列 $a がそのまま渡される あれ違うな 単純な代入だけでなく Comma operator も特例になるのか >>691 特例だとか自分勝手な解釈をする癖を直さないと、他人とのコミュニケーションで苦労するぞ(主に周囲の人間の方が...)。 自分が既に頭の中に描いているイメージに合わせて無理に解釈方法を寄せていくのではなくて、本来理解すべき仕様の方に自分の中の理解を修正して近づけていく方がいいぞ。 >>692 TPO をわきまえられずトンチンカンな御高説垂れる人も、他人とのコミュニケーションで苦労するぞ(主に周囲の人間の方が...)。 >>690 原理的にはジャグ配列にして空評価させて返すで合ってると思う 恐らく処理系のソース読み込まないと判らないよ 配列返す関数作る時も同じ方法 ,$a は Comma operator で1要素の配列を返すけれど その時に $a は展開されずに2次元配列のまま これは単純な代入と同じ扱いだよね { $a } は { Write-Output $a } の事 Write-Output に配列を渡した時の挙動を考えればいい https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/write-output By default, Write-Output enumerates through collections provided to the cmdlet. However, Write-Output can also be used to pass collections down the pipeline as a single object with the NoEnumerate parameter. ウザかろうと思って特例云々につっこむのやめたけどやっぱり書くわ 代入は代入でしかなく特例も何もない いつだって右辺の値をありのままの型と値で代入するだけ $b=&{$a} というのを代入として認識するからおかしくなる $b=$a.Rank と書いたら$bは数値になるわけだけど、代入したから数値になった!とは思わないでしょ あくまで.Rankを評価した結果が数値になって、その数値を$bに代入したに過ぎない $b=&{$a} も &{$a} の評価結果が一次元配列になる仕様なだけで、代入が何かの法則性に寄与している訳ではないし、一次元配列になるという一貫したルールや思想があるわけでもない operand を展開してから operator にわたすんじゃなくて operand をそのままわたして operator が展開したりしなかったりする たぶん理解した >>682 の$b = $a は$aの参照を$bに代入している $a = [Object[,]]::new(3,3) $b = $a $b[0,0] = 1 echo $a[0,0] #=> 1 $b = & { $a } は { $a }というスクリプトブロックを実行して戻り値を代入する { $a } の意味は >>697 を見ろ >>694 初学者が変な誤解すると二度と修正する機会ないからな みんな巡り巡って自分が被る迷惑を未然に防ごうと必死なわけよ こんなシェルを書きました。 function get_stop_code { $hoge=(Get-Content stop_code.txt) } while ($true) { get_stop_code Write-Output $hoge } シェル実行中に、stop_code.txtの中身を書き換えても get_stop_codeがファイルの中身を拾ってくれません いろいろ試したら、こうしたらうまくいきました。がすっきりしません。 function get_stop_code { $hoge=(Get-Content stop_code.txt) Write-Output $hoge } while ($true) { $stop_code=(get_stop_code) write-output $stop_code } get_stop_codeがファイルの中身を、while ($true)の中でうまく拾ってくれる 書き方を教えてください。 スコープの話だと思うよ 関数の内側で変数を書き換えてもローカルスコープ内の変数の更新にしかならないので、関数から戻ったら値は書き換わってない 関数を次のように書き換えて明示的にスクリプトスコープの変数を更新してやればいい function get_stop_code { $script:hoge=(Get-Content stop_code.txt) } PSのスコープって特殊で悩ましい 特にループの初回、ほかの言語みたいに未宣言の変数だぞとエラーになってくれればまだいいんだけど、変数が作られて親からも見えちゃうから混乱する おれも一瞬ではなく数分、>>703 の問題がわからなかった とりあえず頭にSet-StrictMode -Version Latestを付けとけばエラーにはなる >>705 ありがとうございます。 >関数の内側で変数を書き換えてもローカルスコープ内の変数の更新にしかならないので、関数から戻ったら値は書き換わってない というのは、 >>703 だと、 同じシェル内にある$hogeであっても、 @get_stop_code関数内の$hoge Awhile ($true)内にある$hoge の2種類があり、 while ($true)内で、get_stop_code関数を実行しても、 @の$hogeしか書き換わらないから、求める結果が得られない。 って事でしょうか。 そんな感じ 関数はローカルスコープを作る whileの方はその外側にあたるから親スコープになる ちなみにPSではwhileブロックはローカルスコープを作らないのでスクリプト全体のスコープと同じ >>708 ありがとうございます。 スコープですね、勉強になりました。 きっと、しっかり理解すれば便利な仕様なんでしょうが、 初学者にとっては罠でしかありませんね・・・こういうの・・・。 ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる