スクショなどのファイル名のスペースやカッコなどをPythonで一括置換した

# モチベーション

macOSやLinuxでスクリーンショットを撮ると、`スクリーンショット 20××-11-22 33.44.55.png`や`Screenshot from 2021-04-19 14-19-39.png`などのように**スペース**が含まれてしまう。

また同じ名前のファイルをダウンロードすると、`test (1).png`などのように**スペースとかっこ**が含まれていて、コマンドでの操作が非常にやりにくい。

そこで、そのディレクトリにあるファイル名の**スペースやかっこなどの記号を一括置換するプログラム**をPythonで書きました。これを~~`~/Downloads`やら`~/Pictures`やら`~/Desktop`のディレクトリに1個置いておくだけで、~~かなり便利になると思います。（updated）

なおmacOSの場合の、`スクリーンショット 20××-11-22 33.44.55.png`の`スクリーンショット`という日本語の部分は「[Macのスクリーンショットの保存先と名前を変更する](https://qiita.com/makky_tyuyan/items/e308bf1ae1f883152004)」でも排除できます。

# コード

```python
import os
import shutil


def get_filenames(path):
    files_and_dir = os.listdir(path) # get a list of names of files and directories
    files = [i for i in files_and_dir if os.path.isfile(os.path.join(path, i))] # a list of names of only files
    return files


def replace_a_with_b(path, a, b):
    files = get_filenames(path)
    for f in files:              # For example, if f="test 1.pdf", we want to replace a=" " with b="_".
        if a in f:               #
            g = f.replace(a, b)  # g = "test_1.pdf"
            shutil.move(f, g)    # mv 'test 1.pdf' test_1.pdf


def main():
    path = "." # current directory
    replace_a_with_b(path, " ", "_")
    replace_a_with_b(path, "(", "")
    replace_a_with_b(path, ")", "")
    # ここに追加したいものを書いてください


if __name__ == "__main__":
    main()
```

Ubuntuの`~/Pictures`で実行

```bash
Pictures $ ls
total 360K
-rw-rw-r-- 1 <user> <group> 158K Apr 18 22:17 'Screenshot from 2021-04-18 22-17-40.png'
-rw-rw-r-- 1 <user> <group> 140K Apr 19 14:19 'Screenshot from 2021-04-19 14-19-39.png'
-rw-r--r-- 1 <user> <group>  783 Apr 19 23:24  renamefiles.py

Pictures $ python renamefiles.py

Pictures $ ls
total 360K
-rw-rw-r-- 1 <user> <group> 158K Apr 18 22:17 Screenshot_from_2021-04-18_22-17-40.png
-rw-rw-r-- 1 <user> <group> 140K Apr 19 14:19 Screenshot_from_2021-04-19_14-19-39.png
-rw-r--r-- 1 <user> <group>  783 Apr 19 23:24 renamefiles.py
```

# 問題点

置換したい文字を追加すればするほどforの回数が多くなってしまって、あまり効率がよくない気がします。「もっとこうしたらいいよ」というのがありましたらぜひ教えてください。


# 改善

パス名を引数として渡すことで、コマンド的に使えるようにしました。

```python:renamefiles.py
import os
import shutil
import sys


def get_filenames(path):
    files_and_dir = os.listdir(path) # get a list of names of files and directories
    files = [i for i in files_and_dir if os.path.isfile(os.path.join(path, i))] # a list of names of only files
    return files


def replace_a_with_b(path, a, b):
    files = get_filenames(path)
    for f in files:              # For example, if f="test 1.pdf", we want to replace a=" " with b="_".
        if a in f:               #
            g = f.replace(a, b)  # g = "test_1.pdf"
            shutil.move(f, g)    # mv 'test 1.pdf' test_1.pdf


def main():
    if len(sys.argv)!=2:
        print("Usage: renamefiles <path_to_files>")
        sys.exit(1)
    else:
        # path = "." # current directory
        path = sys.argv[1]
        replace_a_with_b(path, " ", "_")
        replace_a_with_b(path, "(", "")
        replace_a_with_b(path, ")", "")


if __name__ == "__main__":
    main()
```

これをホームディレクトリなどに置いておき、`~/.bashrc`に以下を追加してください。

```bash
alias renamefiles="python ~/renamefiles.py"
```

終わったら

```bash
source ~/.bashrc
```

を実行すれば準備完了。

実行例は

```bash
$ renamefiles /path/to/files
$
```