OmniAICreator/Qiita-1.07M huggingface dataset:
通信プロトコル ftp http https の違い

## 〜宣伝〜

:::note info
個人開発でエンジニア専門マッチングサービスを開発しましたので、是非未経験からエンジニア目指している人！現役エンジニアで教えたい人！使ってみてください！

β版リリース記念キャンペーン中です！

10名様限定、抽選でお好きな技術本1冊プレゼント！
🎉当選者にはメッセージ差し上げます(送付の際に住所はお聞きしません)
詳しくはこちらから↓

https://x.com/dokupro01/status/1796837336145436846
:::
https://dokupro.dev/

# 目的

- 実はあまりわかってないftp http httpsについての基礎知識をまとめる。

# 通信プロトコルとは？

- 通信を行う際の共通のルールのことである。
- OSや端末は違っても一定の通信が行えるように規格化されたものである。

# ftpとは？

- ftpはFile Transfer Protocolの略である。
- インターネットの誕生と共に使用され始めた古の頃からの歴史ある技術である。
- ファイルを転送するための通信プロトコルである。
- インターネットを使用してファイルを送受信するための仕組みである。
- ftpを使って通信をするコンピュータやソフトを「ftpクライアント」と呼ぶ。
- ftpを使って通信を受け入れる側のコンピュータ(接続先)を「ftpサーバ」と呼ぶ。
- ファイルをやり取りする時に使用するftpクライアント側のソフトを「ftpソフト」と呼ぶ。

# httpとは？

- httpはHyper Text Transfer Protocolの略である。
- Webページを構成するHTMLなどのコンテンツの送受信に用いられている。
- World Wide Webにおいて、 WebブラウザとWebサーバ間での転送に用いられる。
- ハイパーテキストを転送するための通信プロトコルである。
- ハイパーテキストだけでなく、バイナリ形式の画像、音声などの様々なデータを転送可能である。

# httpsとは？

- httpsはHyper Text Transfer Protocol Secureの略である。
- 基本的な用途や概要はhttpと一緒である。
- 厳密に言うとhttpsは通信プロトコルではないらしい。SSL/TLSプロトコルを用いて行われるhttp通信を指す。
- 通信内容がTSL(Transport Layer Security)によって暗号化されている。
- セキュアで安心である。
【Flutter】'initialCameraPosition != null' : is not true.が起こった時の解決策

#なりゆき
以下のページを参照しながらコピペをしていると途中で画像のエラーが起きた。
[Google公式Flutter用Google Mapsプラグインを一通り使ってみた](https://qiita.com/aoinakanishi/items/25f2526fc7c1fe8350c6)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533444/67c98215-52aa-c3e1-6898-7b1a9e3d0c1d.png)


#解決方法
initialCameraPositionがnullということなのでカメラの初期座標を設定する。

```dart:lib/main.dart
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        height: MediaQuery.of(context).size.height,
        width: MediaQuery.of(context).size.width,
        child: GoogleMap(
          onMapCreated: _onMapCreated,
          //以下に座標を追記
          initialCameraPosition: CameraPosition(
            target: LatLng(35.692558, 139.699530),
          ),
        ),
      ),
    );
  }
```

#結果

最低限表示はされた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533444/03f086c0-b089-81f4-7b26-f57a82cd633a.png)
Fin-JAWS勉強会 第6回

[Fin-JAWS](https://fin-jaws.doorkeeper.jp/)（金融とFinTechに関するJAWS支部）の[第6回](https://fin-jaws.doorkeeper.jp/events/99381)の勉強会に初めて参加させていただきましたので、アウトプットしたいと思います。

①[Best practice of CI/CD and Vulnerability test](https://www.slideshare.net/ShinichiroKawano/2019-1107-finjaws5min)
・[F-Secure](https://www.f-secure.com/jp-ja)社。
・自動化されたシステムリリースにおいて脆弱性診断を行うツールを紹介。
・セキュリティ診断もサービスとして提供している。

②re:Inventで金融をイノベーション～2019への流れ、期待、楽しみ方
第一回から毎回、参加しているとのことでイベントの楽しさを熱く語られていました。
・[CASB（キャスビー）](https://securityblog.jp/words/casb.html)
・[Frank Fallon](https://www.youtube.com/watch?v=CRY_-oApNAI)。VP of AWS。

③[re:Invent2019](https://reinvent.awsevents.com/?&trk=el_a131L0000058OT0QAM&trkCampaign=AWS_reInvent_2019&sc_channel=el&sc_campaign=SessionCatalog&sc_outcome=Strategic_Events)の見どころ
・今年は日本から参加する金融関係者は約150名で昨年よりも多い。
・金融関係の[セッション](https://www.portal.reinvent.awsevents.com/connect/search.ww?trk=el_a131L0000058OT0QAM,el_a131L0000058OT0QAM)も多数ある。
・[日本の登壇者もいました！](https://www.portal.reinvent.awsevents.com/connect/search.ww?trk=direct,direct#loadSearch-searchPhrase=japan&searchType=session&tc=0&sortBy=abbreviationSort&p=)アウェイで凄いですね。[sansan](https://jp.sansan.com/lp/shimei_2.html?ugad=qOzKz9jq&argument=7FEknpAF&dmai=a5d132a138513e&gclid=EAIaIQobChMI_ePJwtnm5QIVQ2oqCh0M_QoBEAAYASAAEgJre_D_BwE)社。

④LT #1 HTTP/2とAWSのはなし
・経路の途中にHTTP1.1にしか対応していないことによる不具合の経験則のお話。

⑤LT #2 KMSを活用した野良アカウント対策
・[Japan Degital Desigen](https://japan-d2.com/)社。
・Service catalog で配布。
・KMSキーポリシー変更は管理者だけ。
・情報が漏洩しても複合化できない。

⑥LT #3 LAAS（Loan As a Service）をAWSで構築
・[UPWARDS](http://upwards.jp/)社。
・金融機関出身者の方。
・スマホアプリにより融資のハードルを下げている。資金回収が気になります。

プレゼン資料を公開していただけると嬉しいのですが。。
space-betweenを使っても中央揃えにならないとき

# 謎の余白
flexboxって凄い便利ですよね。
細かい数値なんかを指定しなくてもいい感じに
キレイに並べてくれる素晴らしいものでお使いの方も
多いのではないかと思うんですけど今回こんな風にズレてしまって
少し困ったのでメモとして解決策を残しておきます。
![EJVshJAUYAAavPS.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519093/3e18cd9c-a36c-8efd-899c-8df121aabcbb.jpeg)

# 空のclassを用意する。
いやもう本当にこれだけです。
どうも疑似要素::beforeを使用していたことが原因のようでした。
space-around等の別のもので指定しても謎の余白は消えなかったので
疑似要素とはあまり相性が良くないみたいですね。
当然ですが::afterでも結果は変わりませんでした。

そしてこちらが擬似要素ではなく空のクラスを用意したもの
![EJVshJEUUAEvBcu.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519093/1c55c48b-3dc1-b4b6-b692-1f71d8d7abea.jpeg)
右にあった謎の余白がキレイに消えてますね。
空のclassはできれば使いたくなかったんですけど
一応解決はしているのでしばらくはこれでいきたいと思います。
TreasureData sftpサーバのCSVファイルをデイリーでワークフローでテーブルにインポート

TreasureDataのテーブルにsftpサーバのCSVをワークフローでインポートする方法のメモ

【やりたいこと】
sftpサーバに毎日送られてくる売上CSVを毎日特定のTreasureDataのテーブルにインポート（テーブルは毎日上書きされその日のCSVデータだけが格納）する。

【売上CSVの前提】
売上CSVのファイル名には年月日時分秒が付いてくる。
2019年11月14日の売上CSVの場合
「Sales20191114235959.csv」
となる。

【ワークフロー作成手順】
①とりあえず空のワークフローを作成
・Workflowsの「New Workflow」ボタンを押す
・"Create Workflow"の入力項目を入力する

```ruby:CreateWorkflow
Workflow Name：ワークフロー名
Project Name：ワークフロー名と同じ
Workflow Template：Blank
```
・もう一度「New Workflow」を押すと空のワークフローが作成される


②ワークフローの定義（dig）を作成
・①で作成したワークフローを選択
・"Workflow Definition"を選択
・[Edit Workflow]アイコンを押す
・digファイルに以下の内容を記述（毎日8:10に処理を実行する場合）

```ruby:workflow.dig
timezone: "Asia/Tokyo"

schedule:
 daily>: 08:10:00

_export:
  td:
    _db: db_name
    _table: table_name

+load_step:
  td_load>: yaml/import_csv.yml
  database: ${td._db}
  table: ${td._table}
```
＜注意点＞
＞: の後にスペースが無いとエラーになる
＞事前にインポート先のテーブルを作っておかないとインポートされない

③インポートの定義（yml）を作成
・[Add Project File]アイコンを押す
・ファイル名に"yaml/import_csv.yml"を入力
・"yaml/import_csv.yml"に以下の内容を記述

```ruby:yaml/import_csv.yml
---
in:
  type: sftp
  host: sftpサーバのipアドレス
  port: 22
  user: sftpLoginID
  password: password
  user_directory_is_root: false
  path_prefix: "/csv_path/Sales"
  path_match_pattern: ${moment(session_time).format("YYYYMMDD")}.*csv
  parser:
    charset: MS932
    newline: CRLF
    type: csv
    delimiter: ","
    quote: "\""
    escape: "\""
    trim_if_not_quoted: false
    skip_header_lines: 0
    allow_extra_columns: false
    allow_optional_columns: false
    columns:
    - {name: id, type: long}
    - {name: description, type: string}
out: {mode: replace}
exec: {}
filters:
- from_value: {mode: upload_time}
  to_column: {name: time}
  type: add_time
```
＜注意点＞
＞: のあとにスペースを入れないとエラーになる
＞charsetはモビルスーツの型番と間違えてしまいそうな謎の"MS932"、日本語のデータがあるからと"SHIFT-JIS"としてしまうと文字化けする
＞columnsはデータに合わせて変えてください
・「Save & Commit」ボタンを押して内容を保存
送るメニューから画像をクリップボードにコピーする

## 画像ファイルをクリップボードにコピーしたいとき

1. ファイルを右クリック
* 編集で開く
* Ctrl+Aで全選択
* Ctrl+Cでコピー

### 面倒なので、一発でクリップボードにコピーしたい！
というわけで、これ

```ps1:画像をクリップボードにコピーする
PowerShell -Command Add-Type -AssemblyName System.Windows.Forms;[Windows.Forms.Clipboard]::SetImage([System.Drawing.Image]::FromFile('%~1'));
```

## このコマンドをBATファイルにして送るメニューに置く

送るメニューは「ファイル名を指定して実行」から「Shell:sendto」でフォルダーを開く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84612/ff3f6669-6a44-1c26-08c9-1ad1a5b5ce21.png)

右クリックするとこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84612/6e8d0342-03a6-c81e-8707-d17a0633c9f3.png)
raspberryケースのおすすめ

Raspberry Pi 3 B +用ファン付き超薄型アルミブラックボックスケース[急速冷却]
https://www.amazon.co.jp/gp/product/B07R9Y1YK4/
Geekworm ラズベリーパイ4（Raspberry Pi 4）用金属ケース、ファン付きのシェル、ラズベリーパイ4コンピューターモデルB適用 (黒色)
https://www.amazon.co.jp/gp/product/B07VF82T12/

この２つのケースおすすめします！
ケースがかっこいいです！！
KODIの日本語化する

各OSに合うKODIをインストールする

設定選択

インターフェース選択

スキン選択

フォント選択し
Arialを選択すれば日本フォント再生出来ます。

地域
地域押し言葉をjapaneseに選択してあげれば
日本語化完了します
iOSでクラッシュレポートにありそうなデバイス/アプリ/システム情報を取得する

Firebase Crashlytics などのクラッシュレポートには、デバイスのモデル情報や、アプリのバージョン、メモリ使用量など、クラッシュの原因調査に役立ちそうな各種情報が一緒にレポートされて便利ですよね。それらの情報を iOS で取得する方法をここにまとめておきます。

## デバイスの情報

### iOSのバージョン

```swift
import UIKit

func osVersion() -> String {
    return UIDevice.current.systemName + UIDevice.current.systemVersion
}
```

### モデル名
```swift
import Foundation

func modelName() -> String {
    var size = 0
    sysctlbyname("hw.machine", nil, &size, nil, 0)
    
    var machine = [CChar](repeating: 0, count: size)
    sysctlbyname("hw.machine", &machine, &size, nil, 0)
    
    return String(cString: machine)
}
```

### アプリのバンドルID

```swift
import Foundation

func appBundleIdentifier() -> String? {
    return Bundle.main.bundleIdentifier
}
```

### アプリのバージョン

```swift
import Foundation

func appVersion() -> String? {
    return Bundle.main.infoDictionary?["CFBundleVersion"] as? String
}
```

## システム情報

### メモリ使用量

```swift
import Foundation

func memoryUsage() -> UInt64? {
    var info = mach_task_basic_info()
    var count = UInt32(MemoryLayout.size(ofValue: info) / MemoryLayout<integer_t>.size)
    let result = withUnsafeMutablePointer(to: &info) {
        task_info(mach_task_self_,
                  task_flavor_t(MACH_TASK_BASIC_INFO),
                  $0.withMemoryRebound(to: Int32.self, capacity: 1) { (p) in
                    UnsafeMutablePointer<Int32>(p)
            },
                  &count)
    }
    return result == KERN_SUCCESS ? info.resident_size : nil
}
```

### URLディスクキャッシュ使用量

```swift
import Foundation

func urlDiskCacheUsage() -> Int {
    return URLCache.shared.currentDiskUsage
}
```
用語解説：オーバーロード

オーバーロードとは

・多重定義、overload
・同一クラスの中で行う（？）
・オブジェクト指向プログラミングの技法のひとつ
・引数や戻り値が異なるが名称が同一のメソッドを複数定義すること
・同一名称の関数（メソッド）を複数個定義し、引数の違いで区別する
　※メソッドは、クラス内に定義した関数。処理の塊、手法。

・引数の型が異なる同名のメソッドを予め複数定義しておく
　→　メソッドを呼び出すときに選択肢ができる
　→　引数・戻り値の型に応じて適切なメソッドの呼び出しが可能
　→　呼び出し時のチェック・メソッド内部での条件分岐を減らせる
　→　可読性・保守性が向上する

【メリット】
　・メソッドの煩雑化防止
　・似て非なるメソッドの大量記述の防止

【デメリット】
　・増えすぎると機能を理解しづらいメソッドを生む可能性あり


”オーバーロードの本質は
『引数や戻り値、個々の振る舞いは異なるが、振る舞いの本質は同様』の場合のメソッドかコンストラクタに対して適用するべきであり、
『引数の型が異なるだけで振る舞いは同様』の場合のメソッドをオーバーロードしても混乱のもととなりやすい。”

だそう。ちょっと難しい。自分なりの言葉で言い直すとしたら、

『振る舞いは同じだけど引数の型が違う』メソッドを沢山作るのは混乱を招くもとだから好ましくない。『引数、戻り値、呼び出し後の振る舞いは全然違うけど本質は同じ』という場合に使用するとよい。対象はメソッドやコンストラクタ。コンストラクタは、インスタンス化の時に生成・実行されるメソッドのこと。

かな。認識ミスがありましたらご指摘ください。

実際にコーディングに入った周りの人やさらにその周りの人の声を聞く限り（残念なことに私はまだ入れていないし予定もない）、概念的・業務内容的どちらにおいても『型』を見極めることが難しいのだそうだ。これは実践・経験あるのみなのかなと今は思っている。

オーバーライドについてはまだ調べられていないので、ここか別のところで別途書き残せればと思います。
Beatlesの数々の名曲から頻度の高い単語をWordCloudで可視化（makemv, mvexpandコマンド編）

きっかけ
---
- 映画Yesterdayを見て、Beatlesの音楽を懐かしむ
- 形態素解析でおしゃれなことをする記事を発見
- まずは英単語なら簡単に区切ることができると考え手っ取り早くword cloudで可視化してみた

で、こんなアウトプットを用意してみた。
---
![Nov-14-2019 23-20-29.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/c971284d-c66b-88c6-d69f-63ce4fa55e19.gif)


利用するもの
---
- beatlesの歌詞一式 (https://github.com/JohannesBuchner/zwicky-morphological-analysis)
    - Webスクレイピングしなくてもとっくにcsvで用意されている。さすが。
- Wordcloud Custom Visualization （https://splunkbase.splunk.com/app/3212/）
    - 可視化のためのApp
- Lookup File Editor （https://splunkbase.splunk.com/app/1724/）
    - lookupファイルの中身の編集を楽にするapp


How to
---
### 1. bealtesの歌詞がすべて記載されたlookupファイルをSplunkに登録
- beatles-lyrics.csvファイルをインポート

<img width="1276" alt="スクリーンショット 2019-11-14 23.06.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/6657c70f-865d-f2b9-2e5f-366491283842.png">

![スクリーンショット 2019-11-14 23.04.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/0712cf23-dc98-7c35-0141-bfe12535706b.png)

- lookupの定義
    - |inputlookupコマンドでサーチできるようにするためにlookup定義を設定
  
![スクリーンショット 2019-11-14 23.08.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/74442b64-1255-f1e8-f780-6dde4ccee800.png)

- lookup file editorでフィールド名とか任意に変更
    - lylicsのフィールド名を扱いやすいsongに変更した
![スクリーンショット 2019-11-14 23.11.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/05547caa-6faf-47fa-cef2-042751e4888f.png)



- |inputlookupコマンドでデータcheck
![スクリーンショット 2019-11-14 23.09.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/a2137b3b-f70b-aa44-0af6-b07ed2c222a5.png)


### 2. SPLを使って可視化
- とりあえず全部まとめたら以下のSPLです

```shell-session
| inputlookup beatles
| table song
| makemv delim=" " song
| mvexpand song
| stats count by song
| sort 200 - count
```

### ポイント①： makemv
- songのフィールドの中身をスペース区切りで分ける

![スクリーンショット 2019-11-14 23.15.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/fe14c1f5-253f-3843-deed-424e41150cb0.png)

### ポイント②： mvexpand
- songのフィールドに複数の値が入っているものを１つ１つのイベントに分ける（パット見上と変わりないが、１イベントごとに別れています）

![スクリーンショット 2019-11-14 23.17.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/aec725bd-debc-1a6b-08c6-10f3b52dc310.png)

- 後は全部まとめて、完成
![スクリーンショット 2019-11-14 23.24.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/58794624-6bdb-c62b-6503-765a73888584.png)



チューニングポイント
---
- この単語外したいなと思ったら、以下の行をサーチに追加

```shell-session
| search NOT song IN (you,to,the,I,and,a)
```

- 少し中身が変わりました。

![スクリーンショット 2019-11-14 23.24.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/a81de9db-d2d8-cf32-7f95-e391de75c220.png)


### 英語はスペースで区切れるので比較的簡単にwordcloudにして可視化できます.

### 次は日本語を使った形態素解析にチャレンジした話もいずれどこかで載せます。
![スクリーンショット 2019-11-14 22.26.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185759/51f8dade-cb94-489c-c0bc-1f2b43690b43.png)
Polynote を使ってみる

# Polynote とは
[Polynote](https://polynote.org/) は[先日 Netflix が公開した](https://medium.com/netflix-techblog/open-sourcing-polynote-an-ide-inspired-polyglot-notebook-7f929d3f447) notebook です。 
Jupyter Notebook のようなものだと考えるとイメージしやすいと思います。
現在は Scala、Python、SQL に対応していて、セルごとに使い分けられるのが特徴的です。
今回は環境構築をして簡単なコードを動かすことを目標にやっていきます。


# 環境構築
macOS Catalina での動作を確認しました。
[公式ドキュメント](https://polynote.org/docs/01-installation.html)を参考に。

## Spark
Apache Spark が必要になります。
英語ですが[このブログ](https://intellipaat.com/blog/tutorial/spark-tutorial/downloading-spark-and-getting-started/)が非常に参考になりました。
筆者の場合は既に JVM や Scala を入れていたので、Spark のインストール部分のみ行いました。
Java は Java8 を選ぶのが無難だと思います。 cf. [Stack Overflow: spark-2-4-java-11-compatibility](https://stackoverflow.com/questions/55269788/spark-2-4-java-11-compatibility)

## Python
Python3 と pip3 が必要なのでインストールしておきましょう。
いくつかの依存パッケージをインストールします。

```bash
pip3 install jep jedi pyspark virtualenv
```
必要なら `pyspark` や `pandas` なども入れておきます。

## Polynote
まず[ここ](https://github.com/polynote/polynote/releases)から最新のバージョンのものをダウンロードします。
今回は `0.2.13` の `polynote-dist.tar.gz` を選びました。
そして展開して notebook を立ち上げます。

```bash
tar -zxvpf polynote-dist.tar.gz
cd polynote

./polynote.py  # localhost:8192 にノートブックが立ち上がる
```


# 動かしてみる
基本的な操作については[公式ドキュメント](https://polynote.org/docs/02-basic-usage.html)にあります。

## ノートブックを作成して Spark の設定をする
ブラウザで `localhost:8192` にアクセスします。
![polynote.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190939/5690208c-516f-cf9a-08af-96f91607b1ee.png)

ノートブックを新規作成して Spark の設定をします。
`Configuration & dependencies` の `Spark Config` で
key: `spark.master`
val: `local[*]`
を入れて `Save & Restart` します。
<img width="1006" alt="spark-master-config.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190939/cee928be-18d0-bb57-49e4-5dd2f101888a.png">

## コードを書いて実行
Spark の Dataframe を作って、グラフの描画機能の使ってみます。
以下のコードを入力して実行します。

```scala
import org.apache.spark.sql._
import org.apache.spark.sql.types._

val schema = StructType(
    List(
        StructField("name", StringType, true),
        StructField("point", IntegerType, true)
    )
)
val data = Seq(
    Row("Taro", 10), Row("Jiro", 20), Row("Ichiro", 30)
)
val df = spark.createDataFrame(
    spark.sparkContext.parallelize(data),
    schema
)

df
```
こんな感じになります。
![polynote1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190939/a94efa42-7068-6ed6-0ef5-a6460ff6c56e.png)

`Out` にあるグラフマークをクリックするとモーダルが現れます。
`Measures` の `Mean point` を Y 軸に、 `Dimensions` `name` を X 軸にドラッグアンドドロップし、 `playPlot` をクリックします。
![polynote2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190939/b896f8ab-9a56-d5be-baa4-ca4b02963ff1.png)
グラフが表示されました。

- - -
以上、環境構築をして簡単なコードを動かしてグラフの描画機能を使ってみました。

Polynote は現在ベータ版で、マイナーバージョンアップは数日ごとに行われているような状況なので、環境構築や操作については大きな変更があるかもしれません。

## 参考
- https://polynote.org/
- https://towardsdatascience.com/getting-started-with-polynote-netflixs-data-science-notebooks-47fa01eae156
- https://intellipaat.com/blog/tutorial/spark-tutorial/downloading-spark-and-getting-started/
- https://qiita.com/ksnt/items/16a9e3bb1b8b8b41569d
Windowsでmatplotlibをインストールしようとするとエラーが出るとき

# 環境
Windows 10 64bit
公式から落としたWindows x86-64 MSI installerでインストールした Python 3.8.0 (tags/v3.8.0:fa919fd, Oct 14 2019, 19:37:50) [MSC v.1916 64 bit (AMD64)] on win32 を利用

# 状況
py -m pip install matplotlibすると、
__error: Microsoft Visual C++ 14.0 is required__ というエラーが出る。
VC++をインストールしたら、 __cannot open include file 'ft2build.h' no such file or directory__ というエラーに変わるが依然としてインストールできない。

# 対処法
https://stackoverflow.com/questions/58693012/installing-matplotlib-on-windows-error-cannot-open-include-file-ft2build-h を参考に、https://www.lfd.uci.edu/~gohlke/pythonlibs から非公式のバイナリ？をダウンロード。
ダウンロードしたのは __matplotlibmatplotlib‑3.2.0rc2‑cp38‑cp38‑win_amd64.whl__ というファイル。

`py -m pip install matplotlibmatplotlib‑3.2.0rc2‑cp38‑cp38‑win_amd64.whl`でインストールできる。
試してないが、たぶんこの方法ならVC++は不要。
transformers(ライブラリ)

ネット上で発見した[ライブラリ](https://huggingface.co/transformers/)。
有名な方が公開している様子ですが、[githubのスターも17000個もついてる](https://github.com/huggingface/transformers)のでみんな使ってると思われます。
→[huggingface](https://huggingface.co/)という企業でした。

>As easy to use as pytorch-transformers
>As powerful and concise as Keras
>High performance on NLU and NLG tasks
>Low barrier to entry for educators and practitioners

のとおり、
BERT,GPT,GPT-2,Transformer-XL,XLNet,XLM,RoBERTa,DistliBERTの８つが似たような書き方で実行できます！DistliBERTなど論文でしか見たことないので使い易い形で組み込んでくれていてありがたい。
20200508記載追加：
CTRL,CamemBERT,ALBERT,XLM-RoBERTa,FlauBERT,Bart,T5,ELECTRA,DialoGPT,Reformer と、[どんどん追加されている模様](https://huggingface.co/transformers/index.html)。

# BERT

    !pip install transformers
    !git clone https://github.com/huggingface/transformers.git
    !mkdir output

と作って

    !python /content/transformers/examples/run_lm_finetuning.py \
        --output_dir=/content/output \
        --model_type=bert \
        --model_name_or_path=bert-base-cased \
        --do_train \
        --train_data_file=****_train.raw \
        --do_eval \
        --eval_data_file=****_test.raw \
        --mlm

とやれば、自分のデータでfinetuningしたBERTモデルを作成できます。
train_data_file、eval_data_fileの場所をいじるのと、model_typeを指定すれば（少しパラメータが変わりますが）他のモデルでもほぼ同じように設定可能です。



# GPT-2
昔苦労して実行させたGPT-2も、このtransfomerを使えばわずか３行で。

    !python /content/transformers/examples/text-generation/run_generation.py \
        --model_type=gpt2 \
        --model_name_or_path=gpt2

色々と試せそうなので発見があれば追記していこうと思います。



#RoBERTaを使ったメモ
embedding層を取り出すためのconfigの設定の注意点があったのでメモ。

```python
#@title RoBERTa(モデル読み込み)
from transformers import RobertaTokenizer, RobertaForMaskedLM, RobertaConfig
import torch

#modelが入っているフォルダ指定
folder = '/output'

#embedding層を取り出すため
config = RobertaConfig.from_pretrained(folder)
config.output_hidden_states = True #これ
#config.output_attentions=True

tokenizer = RobertaTokenizer.from_pretrained(folder, config=config)
model = RobertaForMaskedLM.from_pretrained(folder, config=config)
#model = torch.nn.Sequential(model, torch.nn.Linear(768,144))
```

デフォルトだと、embedding層の重みを出してくれない。（文章数×vocab_sizeの行列が取り出されてしまう。）
config.output_hidden_states=Trueにすればよい。
そうすると、文章数*embedding層の数＝768列の各層（12層）が12×文章数×768のtensorで取り出せた。
層の情報のどれを使うかで、
・最終層を使う
・最後の４層をconcate（768*4列になる）／sum／mean
など色々あるそうで。詳細は[この記事](https://mccormickml.com/2019/05/14/BERT-word-embeddings-tutorial/)参照
自分はmeanを使った。

ちなみにconfig.output_attentions=Trueとすると、Attentoinが取り出せるみたいだけど未実験。


#インポートエラー
finetuningを実行しようとしたらエラーが。

```python
!python /content/transformers/examples/language-modeling/run_language_modeling.py \
    --train_data_file=$TEXT_FILE \
    --output_dir=$OUTPUT_DIRECTORY \
    --model_type=gpt2 \
    --model_name_or_path=gpt2 \
    --do_train
```

などとやると

```python
ImportError: cannot import name 'DataCollatorForPermutationLanguageModeling'
```

というエラーが出た。
ネット上をうろうろさまよい、して、結局transformesをディレクトリ事消して、下記のコマンドを実行して再実行したらいけた。

```python
!rm -f transformers
!git clone https://github.com/huggingface/transformers
%cd transformers
!pip install .
%cd ..
```
Net::HTTP#postとNet::HTTP::Postインスタンスを利用したpost(Net::HTTP#request)の違い

net/httpパッケージで簡単なpostリクエストを送ろうとして調べていたら混乱したのでメモ。
(Ruby: ver2.6.3で試した)

---

調べていくとおおまかに2種類の書き方があった。

1つ目が`Net::HTTP#post`を使う方法。

```rb
require "net/http"
require "json"

uri = URI.parse("http://localhost:8000/")
params = { foo: "bar" }
req = Net::HTTP.new(uri.host, uri.port)
req.post(uri.path, params.to_json)
```

もう1つが`Net::HTTP::Post`のインスタンスを作成し、`Net::HTTP#request`でリクエストする方法。

```rb
require "net/http"
require "json"

uri = URI.parse("http://localhost:8000/")
params =  { foo: "bar" }

http_req = Net::HTTP.new(uri.host, uri.port)
post_req = Net::HTTP::Post.new(uri.path)
post_req.set_form_data(params: params.to_json)
http_req.request(post_req)
```

どう違うかわからなかったのでサーバ立ててリクエストを確認した。

---

サーバについては、以下の記事中のコードをそのまま利用させていただいた。

[Ruby 標準ライブラリの WEBrick で Web サーバを作る](https://qiita.com/niwasawa/items/9713adaa3e82b695bce7)

サーバ起動後、前述のコードを実行したときのリクエストがこんな感じになった。

```
# 1つ目
POST / HTTP/1.1

Accept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept: */*
User-Agent: Ruby
Connection: close
Host: localhost:8000
Content-Length: 13
Content-Type: application/x-www-form-urlencoded

{"foo":"bar"}

# 2つ目
POST / HTTP/1.1

Accept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept: */*
User-Agent: Ruby
Content-Type: application/x-www-form-urlencoded
Connection: close
Host: localhost:8000
Content-Length: 34

params=%7B%22foo%22%3A%22bar%22%7D
```

リクエストボディに渡るデータの形式が異なった。

- `Net::HTTP#post`の場合は、JSONがそのままリクエストボディとして渡された。
- `Net::HTTP::Post`インスタンスを利用した`Net::HTTP#request`の場合は、URLエンコードされたハッシュが`key=value`の形式で渡された。

というわけでリクエストボディへのデータの渡され方が異なった。
docを見る限りpostは文字列データ、set_from_dataは文字通りフォームのデータを送る感じなので、用途とかによって使い分けていけばいいんだろうか？

[Net::HTTP#post](https://docs.ruby-lang.org/ja/latest/class/Net=3a=3aHTTP.html#I_POST)
[Net::HTTPHeader#set_form_data](https://docs.ruby-lang.org/ja/latest/class/Net=3a=3aHTTPHeader.html#I_FORM_DATA--3D)
ログファイルが大きすぎて開けない！

#はじめに
**追記し続けたログファイルが肥大化してテキストエディタで開けない！困った！！**

そんなこと、ありませんか？
そんな時はWindows10で標準装備している、**PowerShell**を使ってログファイルを分割しましょう！

#どうやるの？

####まずはPowerShellを起動します
1. [Windows]キーを押しながら[R]キーを押して、「ファイル名を指定して実行」を起動
2. テキストボックスに[powershell]と入力し[OK]ボタン押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428437/20120e6b-073e-5abf-92d6-0b0bd1896b5b.png)

3. Windows PowerShellを起動したら、以下のコマンドを実行します。

```
$i=0; cat .\error.log -ReadCount 100000 | % { $_ > error_$i.log;$i++ }

#下記項目はそれぞれ変更して使用してください。
#  [./error.log]：分割したいファイルパス
#  [-ReadCount 100000]：分割する行数を指定、今回は10万行
#  [error_$i.log]：分割後のファイル名、今回は[error_1.log][error_2.log]...となる
```

このコマンドを実行してしばらく待っていると、数GBあるログファイルを自動でナンバリングして分割してくれます。


あとは分割したファイルを普段使っているテキストエディタで開くだけ、簡単ですね。

#まとめ
~~ログファイルは肥大化する前にローテーションを設定するなどして対策しましょう。~~




##参考文献
- [【Powershell】テキストファイルを分割する]
(http://souegg2.hatenablog.com/entry/2017/10/16/202230)
- [テキストエディタの大ファイル事情【2018年Windows編】]
(https://qiita.com/asny23/items/d77cb5a510678bfb0dda)
rubyでミュージックプレイヤーを作る

ミュージックプレイヤーと言われると、mp3を再生するものだと思いますよね
初心者がかんがえた簡単プログラムなので、mp3は再生できません、dxrubyを使用します。
改善方法があれば、教えて下さい。
必要な機能は、dxrubyです。
`gem install dxruby`を実行してください。

```ruby:musiplayer.rb
require 'dxruby' #dxrubyを呼ぶ

Window.width = 0 #windowのサイズを0に設定
Window.height = 0 #windowのサイズを0に設定
Window.caption = '再生タブ' #タブの名前を再生タブに変える
sound = "" #soundの値を初期化
play = "" #playの値を初期化
loop do
puts"タイプを入力してね\nhelpと入力してね！"
type = gets.chomp #タイプを取得する
if type == "end" #タイプがendなら、exitする処理へ行く
    exit
elsif type == "stop" #タイプがstopなら、音楽を止める処理へ行く
    if play == "1" #プレイしてないのに、stopするとエラーが出てソフトがエラーで落ちるのでそれを防止
        sound.stop #停止
        play = "" #playを初期化する
    else
        puts "何も再生されていません。" #エラー表示
    end
else
    if type == "" #タイプが入力されてないときの処理
        puts "何も入力してないみたいだけど...?"
    elsif type == "play" #タイプがplayだったときの処理
        puts "ファイルのパスを入力"
        path = gets.chomp #ファイルのパスを取得する
        kekka = File.exist?("#{path}") #ファイルが存在しているかを調べる
        if kekka == true
            if play == "1"
                sound.stop
            end
        sound = Sound.new("#{path}")
        sound.loopCount=-1 #永遠に音楽をloopする
        sound.set_volume(300)
        sound.play
        play = "1"
        else
            puts "エラーが発生しました。 今入力したファイルは存在していますか?"
        end
    elsif type == "help"
        moto = "play = 再生します、パスを要求されます。\nstop = 再生時に実行すると、再生中の音楽を停止します。\nend = ソフトを終了します。\n"
        string = moto
        loop do
        print string.chr
        moto = string.chr
        string.sub!(/#{moto}/,'')
        if string.size == 0
        break
        end
        sleep 0.1
        end        
    else
        puts"そのタイプは存在してないみたいだけど...?"
    end
end
end
```
kubernetes v1.15 で使うdockerをインストール方法

kubernetesでdockerを利用する際にハマらないセットアップ手順を紹介します。
kubernetesのインストールドキュメント(v1.15)ではdocker 18.06.2を推奨されているので
こちらをインストールする方法を紹介していきたいと思います。

## 検証環境
OS : Centos7.6（minimal)


## インストール時に参考にする情報
基本的には[公式サイト](https://docs.docker.com/install/linux/docker-ce/centos/)を参考するのが良いと思います。
（リンクはcentosの手順ページになります左側のメニューからご自身のデストリビーションを選択してください）

## docker インストール手順
上記の公式インストールサイトを参考に私が実行したコマンドを以下に掲載します

### 1.古いバージョンをアンインストールする
これにより古いバージョンがあればアンインストールします。これらのパッケージがいずれもインストールされていないことが報告されれば問題ありません。(私の環境ではアンインストールされるものはありませんでした）

```
$ sudo yum remove docker \
 docker-client \
 docker-client-latest \
 docker-common \
 docker-latest \
 docker-latest-logrotate \
 docker-logrotate \
 docker-engine
```
### 2.dockerに必要なユーティリティを先にインストール

```
$ sudo yum install -y yum-utils \
 device-mapper-persistent-data \
 lvm2
```
### 3.yumのリポジトリの追加

```
$ sudo yum-config-manager \
 --add-repo \
 https://download.docker.com/linux/centos/docker-ce.repo
```

### 4.インストールしたいバージョンの確認をする
以下のコマンドを実行すると、インストール可能なバージョンが表示されるので確認します
完全修飾パッケージ名で特定のバージョンをインストールします。完全修飾パッケージ名は、パッケージ名（docker-ce）と、最初のコロン（:）から始まり、ハイフン（-）で区切られた最初のハイフンまでのバージョン文字列（2列目）です。

```
$ sudo yum list docker-ce --showduplicates | sort -r

docker-ce.x86_64   3:18.09.2-3.el7    docker-ce-stable
docker-ce.x86_64   3:18.09.1-3.el7    docker-ce-stable
docker-ce.x86_64   3:18.09.0-3.el7    docker-ce-stable
docker-ce.x86_64   18.06.3.ce-3.el7   docker-ce-stable
docker-ce.x86_64   18.06.2.ce-3.el7   docker-ce-stable
docker-ce.x86_64   18.06.1.ce-3.el7   docker-ce-stable
docker-ce.x86_64   18.06.0.ce-3.el7   docker-ce-stable
```
### 5.dockerをインストール
version 18.06.2をインストール指定するには、「docker-ce-18.06.2.ce」と指定します

```
$ sudo yum install docker-ce-18.06.2.ce
```

### 6.フォルダを作成
docker用のフォルダを作成します

```
$ sudo mkdir /etc/docker
```

### 7.docker serviceの起動
エラーが表示されなければdocker serviceが起動されています

```
$ sudo systemctl start docker
```

### 8.dockerのバージョンを確認

```
$ sudo docker version
Client:
 Version:           18.06.2-ce
 API version:       1.38
 Go version:        go1.10.3
 Git commit:        6d37f41
 Built:             Sun Feb 10 03:46:03 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server:
 Engine:
  Version:          18.06.2-ce
  API version:      1.38 (minimum version 1.12)
  Go version:       go1.10.3
  Git commit:       6d37f41
  Built:            Sun Feb 10 03:48:29 2019
  OS/Arch:          linux/amd64
  Experimental:     false
```
### 9.サービスを自動起動させる

```
$ sudo systemctl enable docker
```

## 参考サイト
https://docs.docker.com/install/linux/docker-ce/centos/
初心者がTwitterと連動したサービスを作る 概要編

# 目次
**ボタンクリックでランダムでペンギンの画像が出るページを作る**
[その1](https://qiita.com/xcx_04/items/c69b6ed1944058fd65d5)
[その2](https://qiita.com/xcx_04/items/30bc4b3ab1e223faf6f7)

---

# 作りたいもの
①ボタンをクリックするとランダムでペンギンの画像が出る
②「ツイートする」ボタンをクリックで出た画像をツイートする

ペンギンの画像にするのは単純にペンギンが好きで撮りためた写真があるから🐧
~~初心者なんだからサイトや参考書に載ってるもの作ったほうがわかりやすいのでは
→単純にモチベが上がらない…~~

# 自分のスペック
- ディレクション・デザイン・コーディングを広く浅くやるWebデザイナー
- HTML・CSSはそこそこ、JavaScript、PHPは調べながらなんとなく
- 仕事ではmac MAMPを使って構築するので基礎はわかっているつもり


# 構築を通じて学びたいこと
・PHPとJavaScriptに慣れる
・Windowsでコーディングできるようにする
・PHPやサーバーなどの環境構築をできるようにする
・GitHubを使えるようにする
・コマンドでgitを使えるようにする

# 不安点
- 他の人のアカウントでツイートするには、認証とか大変かも？
- いきなりTwitterと連携とかプログラミング初心者には難しいのでは？

# まずは段階を踏んで制作してみる
何もわからず突っ走ってボツになるより、まずは簡単にできることから始めてみる
ということで、

①ボタンクリックでランダムでペンギンの画像が出るページを作る
②ペンギンの画像をランダムで定期的にツイートするbotを作る
③ボタンクリックでランダムでペンギンの画像が出て自分のアカウントでツイートできるサービスを作る

という流れで制作してみようと思います。
【Laravel】MAIL_DRIVER=sendmail, MAIL_DRIVER=smtp の違い。PHPのmail関数の挙動。



[Laravelのmailableクラスでメール送信を行う[導入/入門編]](https://www.ritolab.com/entry/38)

>smtp
SMTPサーバーから送信する。一般的な送信方法。
sendmail
PHPのmail関数で送信する。

[PHP: mail - Manual](https://www.php.net/manual/ja/function.mail.php)

### mail関数はSMTPから送信していないのか？


[PHP: 実行時設定 - Manual](https://www.php.net/manual/ja/mail.configuration.php)

> php.ini の設定により動作が変化します。

`sendmail_path` に設定しているパスが呼ばれる

Windows環境の場合は`sendmail_path`が設定されていなければ
`SMTP`に設定されているSMTP サーバーのホスト名または IP アドレス(デフォルトではlocalhost)に
`smtp_port`設定で指定したサーバーに接続するポート番号(デフォルトは25)で接続する。


### Linuxのsendmailコマンド

MAT(メールサーバー)からメールが送信される。


[sendmailコマンドの使い方: UNIX/Linuxの部屋](http://x68000.q-e-d.net/~68user/unix/pickup?sendmail)

[Linux - メール転送エージェント（MTA）の基本](https://www.infraeye.com/study/linuxz47.html)

[sendmailとは｜「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word11134.html)

### 結論

メールを送信する以上はSMTPサーバーから送信している。
SMTPサーバーに直接接続するか、PHPのmail関数の設定に任せるかの違い。
ってことでいいのかな？
LaravelのBladeで配列のフォームパーツを使った時の@errorの指定方法

通常バリデーションでエラー発生時に、@errorは配列で指定していない名前でエラー判定できますが、配列を使っている時に@errorの部分はいつも通りの指定で良かったのか？という事を思いましたが。

翻訳サイト参考
https://readouble.com/laravel/5.8/ja/blade.html

案の定、フォームパーツが配列の時に、バリデーションエラーを発生させたら、そのままだと、システムエラーが発生します。
ErrorException Undefined offset: 5　というような感じで。

デバックして調べてみたところ、@errorの後にドットでつなげば、使えました。
見本はこんな感じです。

```Html見本
<input type="txt" name="title[ja]" class="form-control @error('title.ja') is-invalid @enderror"">
```

調べても見つけれませんたが、これで対応していけば、エラー箇所のフォームパーツの枠を赤枠にしたり、分かりやすくできます。

.jaの所が変数でも問題ないです。

何かの役に立てば、幸いです。

それでは。
GoのHello Worldで詰まった話

# はじめに

今更ながらgolangに手を出してみることに。
本当にしょうもないミスで詰まったけれど、ググっても答えがパッと見当たらなかったので備忘として残しておきます。
（あまりにもしょうがないミスすぎるせい）

# Goのインストール

https://golang.org/
から、Macなのでpkgでインストール

# 早速Hello World

hello.goファイルを作って

```go:hello.go
package main
import "fmt"

func main() {
  fmt.println('hello world')
}
```

```shell-session
$ go run hello.go
./hello.go:5:3: cannot refer to unexported name fmt.println
./hello.go:5:3: undefined: fmt.println
./hello.go:5:15: invalid character literal (more than one character)
```

たった1行Hello World表示するだけなのに、ミスを2個も犯していましたとさ。

# 答え

```go:hello.go
package main
import "fmt"

func main() {
  fmt.Println("hello world")
}
```

1点目：fmt.Println
「Goにおいて1文字目が大文字か小文字かは重要。大文字はパッケージの外から使えるよ」
と解説があったにも関わらず、すっぽ抜けていた…

2点目："hello world"
Goにおいて文字列はダブルクオートで括る必要がある。
普段PHPerなので、変数展開不要な文字列はシングルクオートで括る癖が。

# 結論

サンプルコードは忠実に打ち込みましょう。
エラーメッセージはよく読みましょう。

ということですね。
言い訳すると、fmt.printlnのエラーに関してはそもそもfmtがうまくimportできていないせいかと疑っていた…
新しい言語を学び始める際、こういった本当しょうもなさすぎるミスが逆に面白い。
macOS Catalinaにアップグレードしたら、急にFlutterが使えなくなった話

# 現象

自分のMacBook AirのOSをmacOS Catalinaにアップデートしたら、なぜか急にFlutterが使えなくなってしまった。

具体的には、Android Studio 3.5でFlutterのプロジェクトを開こうとしたりすると、「Dartが悪質なソフトウェアかどうかをAppleでは確認できないため、このソフトウェアは開けません。このソフトウェアはアップデートが必要です。詳しくは開発元にお問い合わせ下さい。」という警告が出てくるようになってしまった。

また、```flutter doctor```コマンドを使おうとしたところ、上記の警告とともに、変なエラーが出て実行できなくなってしまった。。


```
% flutter doctor
/Users/Hitoshi/flutter/bin/flutter: line 183:  4447 Killed: 9               "$DART" --packages="$FLUTTER_TOOLS_DIR/.packages" $FLUTTER_TOOL_ARGS "$SNAPSHOT_PATH" "$@"
```

# 解決策

ターミナルにて、以下のコマンドを実行すればOK。

```
sudo spctl --master-disable
```

ダウンロードしたすべてのアプリケーションを許可してくれるようになるようです。

# ところが

再度Android Studio 3.5でFlutterのプロジェクトを開こうとしたところ、また別の警告が発生。

<img width="532" alt="スクリーンショット 2019-11-14 22.25.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93963/24379d3c-c379-37a9-ae12-5d48a12bcada.png">

プロジェクトを開くたびに出てくるようなので、鬱陶しくて仕方ありません。。

# 解決策2

ターミナルにて、以下のコマンドを実行すればOK。

```
sudo xattr -d com.apple.quarantine /PATH_TO_YOUR_FLUTTER_HOME/bin/cache/artifacts/libimobiledevice/idevice_id
```

```PATH_TO_YOUR_FLUTTER_HOME``` には、flutterのパスを設定してください。

どうやら、「com.apple.quarantine」という拡張属性があって、安全性が保証されていないプログラムに対して、OS側で割り振られているようです。それを解除するためのコマンドが上記のようです。

GitHub issueでもすでに問題になっているようでした。
https://github.com/flutter/flutter/issues/42302

これでようやく動くようになりましたとさ。
やはり安易に現場のPCのOSをアップグレードするのはやめたほうがよさそうです。。（指示があれば別ですが）

しっかりしてくれ、Catalina。

# 参考URL

- [Catalina Beta版で「悪質なソフトウェア〜」と出てインストール出来ない問題と解決策 | 煩悩八百万クリエイター戦記](https://blog.f-arts.work/archives/1203)
- [【Flutter】“idevice_id”は、開発元を検証できないため開けません。への対処法 | やばブロ！](https://yaba-blog.com/flutter-idevice_id/)
手順書とかドキュメントの管理はGithubですればいいんじゃないか

知り合いから手順書（作業メモも含む）について驚くような話を聞いた。

内容としてはこう

- 作業メモを取らせてくれず、キャプチャを取ろうものなら二重管理になるからと止められるらしい。  
→まだ止めてくれるからいいとも思うけど
- 手順書はWordでまとめられてバージョン管理も編集履歴から確認する
- 手順書はプリントアウトして使用する（プリントアウトしたものへの作業メモの書き込みはセーフ）

なので、１つのアイデアとしてGithubとマークダウンファイルで管理・運用すればみんなHAPPYになるんじゃないかとか思う。
普段プログラムをしない人向けに書くので、Gitの手順などは書かないので、悪しからず。
それから、こういう使い方して便利とかあれば教えてもらえると嬉しいです。

## 1. Githubとは
▽Githubの画面
<img width="791" alt="2019-11-14_22h02_00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311866/3f3db1fc-0791-024b-99da-3e69d0b39086.png">
[wikipedia](https://ja.wikipedia.org/wiki/GitHub)より引用
>GitHub（ギットハブ）は、ソフトウェア開発のプラットフォームであり、ソースコードをホスティングする。コードのバージョン管理システムにはGitを使用する。Ruby on RailsおよびErlangで記述されており、アメリカのカリフォルニア州サンフランシスコ市に拠点を置くGitHub社によって保守されている。主な開発者はChris Wanstrath、PJ Hyett、Tom Preston-Wernerである。
>GitHub商用プランおよびオープンソースプロジェクト向けの無料アカウントを提供している。2019年1月より、プライベートリポジトリを無料で提供するようになった。2009年のユーザー調査によると、GitHubは最もポピュラーなGitホスティングサイトとなった。
2018年にマイクロソフトによる買収が発表されている。

書いてあるようにバージョン管理システムである「Git」を使うサービス。
「ソースコード」と書いてあるのでプログラマだけが使うように思うかもしれないけれど、WordやExcel、PDFといったファイルも管理できるので、やり方さえ覚えてしまえば、簡単な社内共有のツールになる。（基本的に無料で使えるけれど、優れた機能がある組織アカウントは有料です）
また、引用にあるように **マイクロソフトが買収すること** を発表している。

といっても、何ができるのかは次で説明。

## 2. Githubでできること
### 2-1. SharePointと変わらずブラウザ上でフォルダ・ファイルを確認できる
一般的にWindowsを使っていてファイル共有をする場合、SharePointやOneDriveを使うことが多い。
どうようにGithubでも一覧表示してブラウザ上でファイルを見ることができる。
フォルダをクリックすればそのフォルダの中が表示されるので、若干表示形式が変わるだけでできることはそれなりにできる

### 2-2. 画像ファイルのアップロードのしやすさ
Githubには「Issue」や「PullRequest」の機能があり、これらの新規作成画面で、画像を記入欄に移動させるだけで画像のサムネイルとリンクができあがる。
あとは、そのリンクをwikiなどに張り付けることで同じ画像を確認することができる。
いちいちコピーして別々のファイルに貼り付けたり、更新のためにファイルを開いて貼り付けなおす手間が一気に減る。
▽画像を入力フォームにドラッグアンドドロップするだけで画像がアップロードされタグが生成される
<img width="791" alt="2019-11-14_22h18_17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311866/54031dd4-0f1a-b816-201a-7bf887e41ff1.png">

### 2-3. Wikiで情報共有
ブラウザ上で説明や手順を書いたりできるページを作成できる。
MarkDown記法で書くことで、例えば目次を作成したり、ドキュメントへのリンクや導入にあたっての説明をブラウザ上に表示することができる。
メモ帳的な表示からHTMLで作ったかのようなページ表示もできる。
一方で簡単にページを作れるので、ページが乱立しやすい。
<img width="779" alt="2019-11-14_22h15_37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311866/4266ed81-81fe-a652-a0b3-91f1ce442c0f.png">


### 2-4. ReadMe.mdでフォルダごとに説明を書ける
2-3のwikiとほぼ同じで、違う点はmdファイル（＝マークダウンファイル）というテキストファイルに保存して、フォルダごとに表示されること。
このフォルダは何のドキュメントが入っているのかや、手順のwikiページへのリンクを書くことで、wikiの乱立も防ぐことができる。

### 2-5. Projectで進捗管理や課題管理
端的に言えば、カンバン形式の管理ツール。
作業者のアサインやラベルの添付、進捗などを管理できる。
画像には「To Do」「In progress」「Done」だけだけど、追加したり名前を変えることもできる。
<img width="1185" alt="2019-11-14_22h27_51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311866/311ec180-3b32-84ec-a816-02a27c010aee.png">

### 2-6. Settingで権限周りの管理
ここまで説明した機能は「リポジトリ」という単位で設定することができる。
リポジトリへのアクセス制限も設定できる。つまり、このリポジトリを世界中に公開することもできるし、一部にだけ公開するともできるようになっている。
Settingからいつでも変更できるので、業務影響の出ない範囲で触ってみることをお勧めします。
※無料アカウントの場合、3アカウントまでしか追加できないので注意。

## 3. 最後は笑顔で
走り書きなので、目的が若干ぶれている内容もある気がします。
けれど、こういうサービスもあるんだくらいで誰かの導入の参考になればありがたいです。
正直なところドキュメントの管理だけでなくプロジェクトの進行とか100点満点の運営ができているところはないと思っています。業種や職種が違うだけで最適解といわれる管理方法も無数にあるわけで、、、。
それでも、いつまでも苦しい環境で作業を続けるよりもより良い環境を目指したほうがいいと私は思っています。
Nightmare.js でEC-CUBEの注文データを程よく自動生成する

## 環境
・EC-CUBE4.0.3
・Node.js

## はじめに
自動で注文データを作ろうと思うと、EC-CUBE3系の頃から[nanasess](https://qiita.com/nanasess)さん作成の Fakerを使った`GenerateDummyDataCommand` コマンドに大変お世話になっています。
4系でも、少し仕込みをしてから ` bin/console e:f:g ` (←アルファベット順なので覚えやすいw)で各種データを作ることができます。
また、[slack から EC サイトの自動注文テストを走らせる (puppeteer)](https://qiita.com/sunadorinekop/items/9d78e7e271748cff8add)も良記事です。

今回は、古参の[Nightmare.js](http://www.nightmarejs.org/) を使って実現しています。
こんな感じで、自動実行できるわけです。

![image](https://user-images.githubusercontent.com/8424850/68849145-e02ce380-0714-11ea-9042-33d7486809bd.gif)

## 背景
なぜ必要だったかというと、作成された受注データをEC-CUBEから基幹系に渡すのに、24Hでテスト稼働して処理のキャパを見たり(` bin/console e:f:g `をcronで回してもいいのですが)、各種データを拡張していたりして小回りを利かせたいのでjsで書きました。
こちらとは別に、JMeterを使ってぶん回すことも実際にはやっています。

## 実行
ソースは[こちら](https://github.com/takeuji/place_order_automation_for_EC-CUBE)になります。

```
$ npm install colors
$ npm install nightmare
```

でインストールした後に

```
node order_by_non_member.js 
```

で実行します。


## 処理
```javascript
co(function* () {
  // 商品詳細画面を表示
  yield nightmare
    .goto(host + 'products/detail/' + productId)
    .wait('.ec-headingTitle');

  // 規格の選択
  yield selectCombo(nightmare, '#classcategory_id1');
  yield selectCombo(nightmare, '#classcategory_id2');
```

レスポンスを待って、次の処理に行く必要があるため
ジェネレータ関数内の要所要所にyieldを書いて、[co](https://www.npmjs.com/package/co)を使うというスタイルです。

これでいざテスト環境で試そうと思ったら、ダイジェスト認証を突破できなかったりオレオレ証明書に引っかかったりしてしまいましたが、`ignore-certificate-errors`がそのまま指定できるおかげで回避できました。
この辺はソースに反映しています。

また、上のソースには書いていませんが、カード決済を選んだ場合に、カード情報を入力せずに何割かは離脱させたりといったこともテスト時にはやっています。
ECでは大丈夫ですが、連携先システム側の挙動を見るために、`"><script>alert(document.cookie);</script>`などのデータを自動入力させるとか、わりとやりたいことをすぐに反映して試せます。

## 最後に
[Puppeteer](https://github.com/GoogleChrome/puppeteer)でawaitで書くのが今風ではありますが、やりたいことは実現できました。
今度は、Puppeteerを触ってみたいと思います。
AWS CLIの出力結果を絞り込む方法

# 前提
Windows Powershellを使った方法です。

# 方法
①まずはCLIのコマンドをオプションなしでそのまま叩きjson形式で出力、どのような階層になっているか確認する

```
　aws ec2 describe-route-tables

{
    "RouteTables": [
        {
            "Associations": [],
            "PropagatingVgws": [],
            "RouteTableId": "rtb-99999999",
            "Routes": [
                
                {
                    "DestinationCidrBlock": "0.0.0.0/0",
                    "GatewayId": "local",
                    "Origin": "CreateRouteTable",
                    "State": "active"
                }
            ],
            "Tags": [],
            "VpcId": "vpc-aaaaaaaa",
            "OwnerId": "111122223333"
        },
        {
            "Associations": [
                {
                    "Main": false,
                    "RouteTableAssociationId": "rtbassoc-aaaabbbbccccddddd",
                    "RouteTableId": "rtb-aaaabbbbccccddddd",
                    "SubnetId": "subnet-aabbccdd"
                }
            ],
.
.
.

```

②json形式からpowershellのカスタムオブジェクト方式に変換、階層を確認する

```
　aws ec2 describe-route-tables | convertfrom-json

RouteTables
-----------
{@{Associations=System.Object[]; PropagatingVgws=System.Object[]; RouteTableId=rtb-99999999; Routes=System.Object[];...

```

③まずは一番上の階層にある項目（ここではRouteTables）を選択し、出力を確認する

```

　(aws ec2 describe-route-tables | convertfrom-json).RouteTables

Associations    : {}
PropagatingVgws : {}
RouteTableId    : rtb-99999999
Routes          : {@{DestinationCidrBlock=0.0.0.0/0; GatewayId=local; Origin=CreateRouteTable; State=active}}
Tags            : {}
VpcId           : vpc-aaaaaaaa
OwnerId         : 111122223333
.
.
.

```
ここで出てきた項目名をselectすることで、必要な情報だけを抽出することができる

④実際にselectを使って絞り込む

```

　(aws ec2 describe-route-tables | convertfrom-json).RouteTables | select RouteTableId,Routes

RouteTableId          Routes
------------          ------
rtb-99999999          {@{DestinationCidrBlock=0.0.0.0/0; GatewayId=local; Origin=CreateRouteTable; State=active}...

```
⑤項目の中にさらに何個か項目がある場合はハッシュで絞り込む

```
(aws ec2 describe-route-tables | convertfrom-json).RouteTables | select RouteTableId,@{Name="gatewayid";Expression={$_.Routes.GatewayId}}

RouteTableId          gatewayid
------------          ------
rtb-99999999          GatewayId=vgw-11112222

```

以上
機械学習などに使う画像データセットをGoogleから無料で簡単にダウンロードする方法

#必要なモジュールをインストール

まずは下のコマンドでchromedriverというモジュールをインストールします。
`brew cask install chromedriver`
Homebrewをまだインストールしていない場合は、
https://qiita.com/pypypyo14/items/4bf3b8bd511b6e93c9f9
このへんの記事を見てみてインストールしてください。

次に、
`pip install google_images_download`
を実行します。

最後に、
`which chromedriver`
でchromedriverのパスを確認します。筆者のMacの場合は /usr/local/bin/chromedriver と表示されました。


#画像をダウンロード
そして、欲しい画像をダウンロードします。

google-images-downloadで100個以上のイメージを取得する場合、chromedriverのパスを指定する必要があります。 今回は最大で1000件集めます。

上記で確認したchromedriverのパスを指定します。私の環境では/usr/local/bin/chromedriverでした。
例えば文鳥についての画像をダウンロードしたければ、
`googleimagesdownload --keywords "文鳥,Java Sparrow" -l 1000 --chromedriver /usr/local/bin/chromedriver`
を実行すればよいです。すると、実行したディレクトリにdownloadsというディレクトリが生成され、その中に文鳥、Java Sparrowという名前のディレクトリも生成されていると思います。

これで完了です。欲しい画像の名前を"文鳥,Java Sparrow"のところに書けばOKです。
Python 配列内の文字列の一括置換

スクレイピングをしていて取得した文字列を配列に格納したとき
配列内の余分な改行が・・・
そんな時に置換 or 削除したいなって場面に遭遇したので
備忘録の意味も込めて

#やりたい事
```python:
str_list = ['あい\nうえお', 'かいくけこ', 'さし\nすせ\nそ', 'たちつて\nと', 'なに\nぬ\nね\nの']
str_list2 = [['あい\nうえお', 'かいくけこ'], ['さし\nすせ\nそ', 'たちつて\nと', 'なに\nぬ\nね\nの'], ['はひふ\nへほ', 'ま\nみむめも\n'], ['やゆよ'], ['らり\nるれろ', 'わをん']]

```
こんな感じでスクレイピングしていると欲しい文字列以外が含まれていたりする

#### これを簡素にしたい
```python:普通
replace_list = []
for s in str_list:
    if '\n' in s:
        text = s.replace('\n', '')
        replace_list.append(text)
    else:
        replace_list.append(s)

print(replace_list)
>>['あいうえお', 'かいくけこ', 'さしすせそ', 'たちつてと', 'なにぬねの']

for i in str_list2:
    for s in i:
        if '\n' in s:
            text = s.replace('\n', '')
            replace_list2.append(text)
        else:
            replace_list2.append(s)
    replace_list3.append(replace_list2)
    replace_list2 = []

print(replace_list3)
>>[['あいうえお', 'かいくけこ'], ['さしすせそ', 'たちつてと', 'なにぬねの'], ['はひふへほ', 'まみむめも'], ['やゆよ'], ['らりるれろ', 'わをん']]
```

####簡素にできた
```python:内包表記
replace_list = [s.replace('\n', '') for s in str_list]
replace_list2 = [[s.replace('\n', '') for s in text] for text in str_list2]

print(replace_list)
print(replace_list2)
>>['あいうえお', 'かいくけこ', 'さしすせそ', 'たちつてと', 'なにぬねの']
>>[['あいうえお', 'かいくけこ'], ['さしすせそ', 'たちつてと', 'なにぬねの'], ['はひふへほ', 'まみむめも'], ['やゆよ'], ['らりるれろ', 'わをん']]
```

内包表記を使っただけだけどこっちのほうがぽい
picoCTF 2019 like1000 - Points: 250

#問題

https://2019game.picoctf.com/problems

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/14b98fe7-dab1-4dd9-d280-9532f77a0c0e.png)

#解いてみた

ダウンロードしたtarファイルを解凍してみる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/36ea4dcb-6052-9134-37ea-d931e2dc7060.png)

これはもしや1.tarまで繰り返す系のやつかな。。。
テキストファイルの中を見てみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/bb2cb39a-e7cf-2d65-b1b8-988bd7d07e6a.png)

何？
999.tarを解凍してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/2461e4c6-228a-213a-1e93-f415e746f068.png)

998.tarができました。
やはり1.tarまで頑張る系みたいですね。
テキストファイルの中身は同じでした。

ubuntuのshellを使って一気に全部解凍してみます。
こんな感じですかね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/e8776b04-8951-abfb-f528-45087d8c07aa.png)

実行するとなぜか609.tarで止まってしまいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/4fc02c3e-b70a-8818-fed0-a20d0173c0c7.png)

なんでかなと思って調べてみると残り容量が0に。。。
ひとつ前のtarを削除する処理を追加する必要がありそうです。
こんな感じで実行してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/2d31d2d3-a870-06d1-f4a6-381cc9771a96.png)

最後にflag.pngが出てきました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/62fc450f-cb1a-29ad-662a-40075bba0335.png)

解けました。
シェルスクリプト Hello World!

##### echo
```shell:hello-world.sh
#!/bin/bash
echo 'Hello World!'
```

##### awk スクリプト
\#!/usr/bin/awk -f で awk スクリプトになる
(-f オプションが必要)

```shell:hello-world-awk.sh
#!/usr/bin/awk -f
BEGIN {
  print "Hello world! by awk"
}
```

##### head コマンド
このスクリプトを実行すると、「/usr/bin/head -2 ./hello-world-tail.sh」が実行される

```shell:hello-world-head.sh
#!/usr/bin/head -2
Hello World! 1
Hello World! 2
Hello World! 3
```

```shell:出力
#!/usr/bin/head -2
Hello World! 1
```

即ち、”1行目のところに書いたコマンド（/usr/bin/head -2) が、スクリプトのファイル名(hello-world-head.sh)を引数に付けて実行されている”ということが分かる。
CollectionGroupを効率的に利用するためのQueryを考えた。

こんばんは、[Stamp Inc](https://stamp.team/)の[村本](https://twitter.com/1amageek)です。

普段はFirebaseの技術コンサルティングをやってます。
最近、古き良き大手さんと契約させて頂きました👏🏻

少しづつですが、大手さんもクラウドを使い始めて本当にいいことだなぁっと思っとります。

今日は__CollectionGroup__の使い方について説明しようと思います。
__CollectionGroup__が出てきた当初に書いた記事があるのでまずここを読んでもらって、さらに適切に使いこなすにはどうすればいいのかを考えました。

[参考] [待ち焦がれたCollectionGroupがCloud Firestoreへやってきた。](https://qiita.com/1amageek/items/343f262ba3b50e657078)

## CollectionGroupがすごいのはReadではなくWrite

__Cloud Firestore__ではCollectionのWriteに制限が設けられています。

![スクリーンショット 2019-11-14 21.47.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80287/04ab602c-695a-d67b-18f7-bdd9729e5e04.png)

| Limit | Details |
|:--|:--|
| Maximum write rate to a collection in which documents contain sequential values in an indexed field | 500 per second |

> インデックス付きのCollectionへの連続的な書き込みは1秒間に500までとなります。

実際かなり大きいので問題になる場合は少ないですが、例えばアクティブユーザー全員が投稿する`posts`なんて言うCollectionをRootに持っていたとすれば性能的に問題になる場面も出てくるはずです。

### CollectionのWrite性能を向上させるテクニック

#### 負荷の高いCollectionは分散させる

Rootに`posts`Collectionを置くのをはやめて、`users/:user_id`の`SubCollection`として`posts`を配置しましょう。

`/users/:user_id/posts/:post_id`

#### CollectionGroupでReadする

分散させたCollectionは__CollectionGroup__で取得出来ます。

```typescript
const snapshot = await db.collectionGroup("posts").get()
```

もう遅いので今日はここまで。
MySQLが[Warning] Access denied for user 'zabbix'@'localhost'を吐く

# 事象

syslogをエラーログを見ていたら以下のエラーが出続けていた

```
2019-11-14 12:54:20 399759 [Warning] Access denied for user 'zabbix'@'localhost'
```

# 対処

[Zabbix 2.2でMySQLを監視する - Qiita](https://qiita.com/iwaim@github/items/8443acf4a4917e5b21fb)
JavaScriptの基本箇所についての復習③(DOM)

#はじめに
jsは色んな事に使える言語ですが、多くはWebページを動的にするために使用されているようです。
この記事からは、jsを使って動的なWebページを作るための手法について書いていきたいと思います。

#内容
動的なWebページを作るために、まずはDOMについて学びたいと思います。

#実行

DOMとは"Document Object Model"の頭文字を取った用語で、
htmlコードのクラスやidをJavaScriptでオブジェクトとして使う事ができる仕組みです。

例えば、

```html
前略
<div class = "btn">押す</div>

```

というhtmlファイルがあったとします。
これは"押す"というテキストに"btn"というクラスがついています。
このテキストの色を赤にしたい時は、cssファイルを用意して

```css
.btn{
 color: red;
}
```
と書いてあげれば良いのでした。
あんまり使われない表現かもしれませんが、
***btnクラスをテキストにつけることによって、cssファイルの"色を変える"という処理を実行する***ともいえます。

同じようにして、***btnクラスをテキストにつけることによって、JavaScriptの特定の処理を実行する***ということもできます。
例えば、"テキストをクリックしたら、コンソール画面（別途投稿予定）に'押されました'と表示される"という処理は次の様に書きます。

```javascript
let btn1  = getElementsByClassName("btn");
btn1.addEventListener("click", function(){
 console.log('押されました');
});
```

見覚えのない文字列が出てきたので、一つ一つ解説していきます。

まず1行目。`let btn1 = `の部分は変数を宣言する部分ですので問題ないかと思います。
初見なのは右辺の`getElementsByClassName("btn");`の部分です。
これは***btnクラスをDOM要素として取得する***という意味となります。

そんなこと言われても、なかなか馴染みが無い表現で判りにくいと思います。
しかし、これからプログラミングと付き合っていく上でこの表現には親しんでいく必要があるので、是非とも慣れていってもらえればと思います。

とはいえ"取得する"というのも最初は判りにくい表現なので、

***htmlファイルのbtnクラスとJavaScriptファイルの変数btn1をdocument.querySector()を使って関連付けさせた。
それにより、JavaScriptに書かれている"変数btn1を使用した関数"の結果がhtmlファイルの"btnクラスがついたオブジェクト"に適用されるようになる***

といったことが起こっていると思ってもらえれば良いと思います。


残りの部分は関数であることは判りますが、```btn1.addEventListener("click", ```部分を見たことが無いと思います。
ここは、```addEventListener```は"こういう時はそういう風に書く"とだけ思ってもらって、その前後について注目してください。
まず後の方にある```"click"```ですが、これは***クリックした時に関数が実行される***という意味になります。
関数が[発火](https://qiita.com/Moon1126Snow/items/85faa8e18be5089e0e1a)する条件を書いています。
```click```はそのまま"クリックする"という意味です。この部分も色々な種類があります。

前方の```btn1.```は、先ほどの```click```を行う対象を指定することになります。
この場合、JavaScriptのコード上での```btn1```に関係する処理は、htmlファイルでの```btn```をクラスに持つオブジェクトで行われる、ということになります。

以上のような流れで、DOMを利用した処理が可能となります。
ここで書かれた事以外にも様々な文法があり、それを利用することで様々な複雑な処理が可能になります。今後の記事では、それを少しずつ解説できればと思います。


#注意
本記事は煩雑になってしまったので、今後定期的に修正を行っていきます。
CentOSでフォルダ階層だけをコピーしたい

# はじめは挨拶
Qiita投稿始めました。
はじめまして。
よろしくお願いします。

# 記事の対象読者

「Linuxもコマンドラインもわからないよ。」なWindowsユーザ

# シナリオ

1. Aフォルダ`sourceDirectory`とBフォルダ`targetDirectory`が存在していて、
2. Aフォルダの**フォルダ構造のみ**をBフォルダへコピーしたい
3. ただし、**特定の名前のフォルダはコピー対象外`excludeDirectory`**としたい

具体的には、
CVSからGitへ移行するときにgit-cvsimportを使用して移行しようと思ったが
git-cvsimportは空フォルダを移行してくれない。

ああああもう困った・・・・。何ができるのコマンドラインって！！！
そんなときに階層を合わせるために使えるコマンドが以下になります（めっちゃ早口）。

# フォルダ階層コピーテンプレ
```shell
$ rsync -avz--exclude "{excDir/}" --include "*/" --exclude "*" {srcDir} {tarDir}
```

- includeとexcludeは前から順に評価されるため記載順序に注意(ハマった)。
  この例では、

  - 1.`excDir`をコピー対象外に設定
  - 2. 1以外のすべてのフォルダをコピー対象
  - 3. 残り(のファイル)はすべて対象外  
  の順に設定しているため表題の件が実現できています。

# 説明
- excDir 除外対象のディレクトリ名（例えば「CVS」「.git」「.svn」などのソース管理ツール固有のフォルダ)
- srcDir 移行元ディレクトリ (例えばCVSからチェックアウトされたプロジェクトフォルダ）
- tarDir 移行先ディレクトリ (例えばgit-cvsimportを使用した際に作成される、空ディレクトリを含まないプロジェクトフォルダ)

移行元ディレクトリ(`aDir`)階層

```shell
# ツリーコマンドで階層を表示
$ tree aaaaDir/

aDir/
|-- CVS   ← このフォルダ以下は移行したくない
|   |-- Entries
|   `-- tmp
|-- a_dir
|   |-- aa_dir
|   |   `-- aaa_file.log
|   `-- aa_file.txt ← ファイルは移行したくない
`-- duplicateDir 
    |-- a_file.txt
    `-- du_aDir ← 重複しているフォルダの下のフォルダ
```

移行先ディレクトリ(`bDir`)階層

```shell
$ tree bbbbDir/

bDir/
|-- b_dir
|   `-- bb_file.txt
|-- b_log.log
`-- duplicateDir

```

rsyncコピー実行

```shell
# -abzはおまじない
$ rsync -avz --exclude "CVS/" --include "*/" --exclude "*" aDir/ bDir/

# 以下は実行ログ(よくわからん)
sending incremental file list
a_dir/
a_dir/aa_dir/
duplicateDir/
duplicateDir/du_aDir/

```

rsyncコピー実行後(`bDir`)階層

```shell
# CVSフォルダは移行されていない
bDir/
|-- a_dir
|   `-- aa_dir # aのファイル群は移行されていない
|-- b_dir
|   `-- bb_file.txt
|-- b_log.log
`-- duplicateDir
    `-- du_aDir #  重複しているフォルダの下のフォルダは移行される

```

# Windowsマン向け番外

- `yum install tree`でtreeコマンドインストール
- `yum install rsync`でrsyncコマンドインストール

以上です。Qiita初投稿楽しかったです。