2018年7月3日火曜日

shやBashの代わりにPythonを使う

勉強の為に転載しました。
https://kyoto-geopython.github.io/Kyoto-GeoPython/html/応用編/shやBashの代わりにPythonを使う.html

目次

  • はじめに
  • pwd: 作業ディレクトリのパスを表示する
  • ls: ファイルをリストする
  • cd: 作業ディレクトリを変更する
  • cp: ファイルをコピーする
  • mv: ファイルを移動する
  • rm: ファイルを消去する
  • mkdir: ディレクトリを作る
  • ファイル操作その他
  • プロセスの実行

はじめに

Pythonの標準ライブラリを用いると、シェルスクリプト(shやbash)と同等の操作がPython上で行えます。
Pythonを用いることには次のような利点があります。
  • Pythonの強力な文字列操作メソッドを用いられる
  • シェルスクリプトの働きとPythonのその他のライブラリ(NumPyなど)とをシームレスにつなぐことができる 
特に後者は、Pythonの強みである「言語自体の汎用性とライブラリによる専門性」を表していると言えるでしょう。
本稿では、Pythonを用いてファイル操作を行う方法と、プロセスを実行する方法について、シェルのコマンドと対応させて簡単に紹介します。

pwd: 作業ディレクトリのパスを表示する

pwdやlsなど、多くのファイル操作コマンドは、標準ライブラリosモジュールを通して実現されています。
現在の作業ディレクトリのパスはos.getcwd()によって得られ、文字列型として返されます。
In [1]:
import os
working_dir = os.getcwd()

ls: ファイルをリストする

ls path は os.listdir(path) で、pathにおけるファイルなどを、文字列のリストとして返してくれます。
In [2]:
ls = os.listdir("./")
for f in ls:
    print(f)
Pandas ― データ分析.ipynb
libsobol.c
c01.csv
Fortran, C言語 との連携.ipynb
.ipynb_checkpoints
シェルスクリプトとしてPythonを使う.ipynb
os.listdirでは、任意の1文字を表す ? や任意の文字 * などのワイルドカード、または正規表現を使うことができません。
ワイルドカードや正規表現を用いて特定のファイル名のみをリストしたいときは、標準ライブラリのglobを用います。
glob.glob(path)で、pathに一致するファイルをリストとして抽出できます。ただし、os.listdirと異なり、ファイル名でなくそのパスを返していることに気をつけましょう。
In [3]:
import glob
ls2 = glob.glob("./*.ipynb")
for f in ls2:
    print(f)
./Pandas ― データ分析.ipynb
./Fortran, C言語 との連携.ipynb
./シェルスクリプトとしてPythonを使う.ipynb

cd: 作業ディレクトリを変更する

cd path は os.chdir(path) です。
Python上での作業ディレクトリの変更は、Pythonのセッションが終了するまで(IPythonなどを閉じるまで)有効です。
In [4]:
os.chdir("../基礎編")

cp: ファイルをコピーする

cpやmvなどのコマンドはshutilモジュールによって提供されています。
cp src dst は shutil.copy(srcdst) です。
In [5]:
import shutil
print(glob.glob("./*.f90"))
shutil.copy("write_binary.f90", "copied_write_binary.f90")
print(glob.glob("./*.f90"))
['./write_binary.f90']
['./copied_write_binary.f90', './write_binary.f90']
また、ディレクトリまるごとのコピー(cp -r)は、 shutil.copytree(srcdst) です。

mv: ファイルを移動する

mv src dst は shutil.move(src,dst) です。
In [6]:
print(glob.glob("./*.f90"))
shutil.move("copied_write_binary.f90", "moved_write_binary.f90")
print(glob.glob("./*.f90"))
['./copied_write_binary.f90', './write_binary.f90']
['./write_binary.f90', './moved_write_binary.f90']

rm: ファイルを消去する

rm path は os.remove(path) です。
In [7]:
print(glob.glob("./*.f90"))
os.remove("moved_write_binary.f90")
print(glob.glob("./*.f90"))
['./write_binary.f90', './moved_write_binary.f90']
['./write_binary.f90']
また、空のディレクトリの消去(rm -r dirname)はos.rmdir(dirname)、
中のファイルも含めたディレクトリまるごとの消去(rm -rf dirname)はshutil.rmtree(dirname)です。

mkdir: ディレクトリを作る

mkdir dirname は os.mkdir(dirname) です。

ファイル操作その他

osのサブモジュールpathは、パスの操作に便利な関数を提供しています。
os.path.exists(pathpathで表されるファイル・ディレクトリが存在していればTrue、存在していなければFalseを返す。
os.path.isdir(pathpathがディレクトリならばTrue、ファイルやシンボリックリンクならばFalseを返す。
os.path.isfile(pathpathがファイルならばTrue、ディレクトリやシンボリックリンクならばFalseを返す。
次の2つは、パスの文字列を場所+ファイル名に分割したり、拡張子を取り出すのに使えます。
dirfile = os.path.split(pathpathのファイル等の場所をdirに、ファイル名をfileに文字列として返す。
rootext = os.path.splitext(pathpathのファイル等の拡張子をextに、拡張子の手前までをrootに文字列として返す。

プロセスの実行 - シェルを呼ぶ場合

上記のファイル操作コマンドだけでなく、Pythonからシェルを呼ぶことで任意のコマンドを実行することができます。 Python 3.5以降はsubprocessモジュールのsubprocess.runを用いることが推奨されていますが、Python 2.xでもos.systemから同様のことができます。
In [8]:
import subprocess
subprocess.run("./a.out > redirected.txt", shell=True) # Python 3.5以降
os.system("./a.out > redirected.txt") # Python 2.x, 現在は非推奨らしい。./a.outがないため正常終了の結果(0)を返さない
Out[8]:
32512
subprocessモジュールからシェルを呼ばない場合や、標準出力・標準エラー出力を得る方法については、こちらこちらをご覧ください。

0 コメント:

コメントを投稿