ほむほむ　作業するなら外付けHDDじゃなくて内臓HDD〜

<div align="center">

<img width="70%" alt="mojikyo45_640-2.gif" src="https://qiita-image-store.s3.amazonaws.com/0/149269/0895707e-6c96-3a43-ea56-577411ce2ed2.jpeg">

</div>

ちょっと遅すぎだわ・・・


# Summary

外付けHDDにデーターを置いていろいろ作業してた

コピーする作業がものすごく遅い

パソコンで作業するなら内臓HDDの方がお得

# Summary2

BashScriptは外付けHDDに関しての作業が苦手？

F#の方がBashScriptより早い気がする

## Environment

```bash

~/tmp
(ins)$ sw_vers 
ProductName:	Mac OS X
ProductVersion:	10.14
BuildVersion:	18A391

~/tmp
(ins)$ uname -a
Darwin callmekoheis-MacBook-Air.local 18.0.0 Darwin Kernel Version 18.0.0: Wed Aug 22 20:13:40 PDT 2018; root:xnu-4903.201.2~1/RELEASE_X86_64 x86_64

~/tmp
(ins)$ bash --version
GNU bash, version 4.4.23(1)-release (x86_64-apple-darwin17.5.0)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

~/tmp
(ins)$ echo 'printfn "%A" <| System.Reflection.Assembly.GetAssembly( typeof<list<int>> ).FullName' | fsharpi --readline-

Microsoft (R) F# Interactive version 4.1
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

> "FSharp.Core, Version=4.4.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
val it : unit = ()
```

## いらいらポイント

外付けHDDから内臓HDDにコピーする作業

## 作業はこんな感じ

外付けHDDにあるデーター（主に写真データー）から必要な写真データーをフォルダ構成を変えて内臓HDDにコピーする（それだけ！）

![foo.jpg](https://qiita-image-store.s3.amazonaws.com/0/149269/f4a989c6-a852-031d-670d-478334c85283.jpeg)

外付けHDDにあるデータの様子

![Screen Shot 2018-11-03 at 4.51.32.png](https://qiita-image-store.s3.amazonaws.com/0/149269/19cb2979-4114-f28b-1f6c-bee7f550e46b.png)


## かかかる時間

F#の方が１分ほど`bash script`より早いが、かなり遅いっ

```
bash script
4m22

F# script
3m39
```

![bash.jpg](https://qiita-image-store.s3.amazonaws.com/0/149269/868762e2-d9b2-6164-f809-9470229700e5.jpeg)


![Screen Shot 2018-11-03 at 2.02.06.png](https://qiita-image-store.s3.amazonaws.com/0/149269/b6e73c35-da7e-aead-b5ea-7d2b1d5aab7b.png)


![Screen Shot 2018-11-03 at 2.02.11.png](https://qiita-image-store.s3.amazonaws.com/0/149269/ec6b5469-51dd-21b7-5ffd-46213fbd44bb.png)



## 内臓HDDでの作業

もしかして？とおもって、パソコンに内臓されている`HDD`に外付けの`HDD`にあるデーターをコピーしてみて、作業したら早くなった！

```
だいたい１分
```

![Screen Shot 2018-11-03 at 3.04.27.png](https://qiita-image-store.s3.amazonaws.com/0/149269/a267cb54-a272-e8c4-483a-5db234a9ba2a.png)

## 書いてみたコード

ばばば、、、と書いたのであれかもしれない。。。

というか、そんなにコードとか書くの得意じゃないのであれかもしれない。。。

`bash script`のコード

```bash
# SrcHDD_='/Volumes/kohei120GB'
SrcHDD_='/Users/callmekohei/Desktop/mytest'
DstHDD_='/Users/callmekohei/tmp4'


function createDstFilePath () {

  echo $1 | sed \
    -e 's/\.JPG/\.jpg/' \
    -e 's/色補正後のデータ\///' \
    -e 's#'$SrcHDD_'/DVD[1-9]/バラ写真#'$DstHDD_'/BA#' \
    -e 's#'$SrcHDD_'/DVD[1-9]/フイルム#'$DstHDD_'/SL#' \
    -e 's#'$SrcHDD_'/DVD[1-9]/ポケットフイルム#'$DstHDD_'/PF#'

}

function copyFiles () {

    local srcFilePath
    local dstFilePath

    while read -r srcFilePath
    do

      dstFilePath=$( createDstFilePath $srcFilePath)
      dstFolder=$( dirname $dstFilePath )

      if [ ! -e $dstFolder ] ; then
        mkdir -p $dstFolder
      fi

      cp -f $srcFilePath $dstFilePath

    done

}

find $SrcHDD_/* -type f \
  | grep '後' \
  | copyFiles
```

`F#` のコード

```fsharp
open System.IO
open System.Text.RegularExpressions

// let SrcHDD_ = "/Volumes/kohei120GB"
let SrcHDD_ = "/Users/callmekohei/Desktop/mytest"
let DstHDD_ = "/Users/callmekohei/tmp4"


// コピーしたい写真データーのリストを作成する
let srcJPGs () =

    ["DVD1";"DVD2";"DVD3";"DVD4"]
    |> List.map ( fun s ->
        Directory.GetFiles( SrcHDD_ + "/" + s ,"*", SearchOption.AllDirectories)
        |> Array.filter ( fun (s:string) -> s.Contains("色補正後のデータ") )
    )

// コピー元のファイルパスとコピー先のファイルパスを組み（タプル）にしたリストを作成する
let dstJPGs () =

    srcJPGs ()
    |> List.map( fun arr ->
        arr
        |> Array.map( fun srcPath ->

            let destinateFilePath =
                Regex.Replace( srcPath, @"色補正後のデータ/" , "" )
                |> fun s -> Regex.Replace( s, SrcHDD_ + @"/DVD\d/バラ写真"         , DstHDD_ + "/BA" )
                |> fun s -> Regex.Replace( s, SrcHDD_ + @"/DVD\d/フイルム"         , DstHDD_ + "/SL" )
                |> fun s -> Regex.Replace( s, SrcHDD_ + @"/DVD\d/ポケットフイルム" , DstHDD_ + "/PF" )
                |> fun s -> Regex.Replace( s, ".JPG", ".jpg" )

            srcPath, destinateFilePath

        )
    )

// もしコピー先のフォルダがなければ作成する
let createFolderIfnotExists () =

    dstJPGs ()
    |> List.map ( fun arr ->
        arr
        |> Array.map( fun tpl -> System.IO.Path.GetDirectoryName( tpl |> snd ) )
        |> Array.distinct )
    |> List.iter( fun arr ->
        arr
        |> Array.iter( fun folderPath ->
            if not ( Directory.Exists( folderPath ) ) then
                Directory.CreateDirectory( folderPath ) |> ignore
        )
    )


let main () =

    createFolderIfnotExists ()

    dstJPGs ()
    |> List.map ( fun arr ->
        arr |> Array.iter ( fun (src,dst) -> File.Copy(src, dst) ) )

main ()
```

## 追記 2018.11.5 mon 00:34

`copy`メソッドをパラレルしてみました！

外付けHDDから内臓HDDにコピーする際パラレルすると大幅に遅くなります！それ以外（同一HD）だと早くなります！ふむ〜。なぜに？？

| parallel | src hdd | dst hdd  | time      |
| :---:    | :-------| :------- | -----:    |
| x        | outer   | inner    | 3m39.562s |
| o        | outer   | inner    | 8m41.194s |
| x        | inner   | inner    | 1m04.923s |
| o        | inner   | inner    |   44.122s |
| x        | outer   | outer    | 9m27.624s |
| o        | outer   | outer    | 8m29.336s |

![IMG_9213.JPG](https://qiita-image-store.s3.amazonaws.com/0/149269/11f9e611-28e8-0f8c-2d94-29aa895ae8c2.jpeg)

コード

```fsharp
let main () =

    createFolderIfnotExists ()

    dstJPGs ()
    |> Array.concat
    |> Array.map ( fun (src,dst) -> async{ File.Copy(src, dst) } )
    |> Async.Parallel
    |> Async.RunSynchronously
```