1 はじめに
ファイルとディレクトリ操作の機能を提供するosモジュールとos.pathモジュールを使ったプログラムを作成して動作確認をしてみます。
2 検証環境
AlmaLinux版数は以下のとおりです。
[root@server ~]# cat /etc/redhat-release AlmaLinux release 9.2 (Turquoise Kodkod)
カーネル版数は以下のとおりです。
[root@server ~]# uname -r 5.14.0-284.11.1.el9_2.x86_64
pythonの版数は以下のとおりです。
[root@server ~]# python -V Python 3.9.16
3 osモジュールの使い方
osモジュールは、OSに依存する機能を提供するモジュールです。 ファイルやディレクトリの操作を行うことができます。osモジュールが提供する関数(一部)を以下に示します。
関数 | 概要 |
---|---|
getcwd | カレントディレクトリ取得する |
chdir | カレントディレクトリを変更する |
listdir | ディレクトリの中身をリストで取得する |
walk | ディレクトリツリーを取得する |
mkdir | ディレクトリを作成する |
rmdir | ディレクトリを削除する |
makedirs | ディレクトリを再帰的に作成する |
rename | ファイルやディレクトリの名前を変更する |
chmod | ファイルのパミッションを変更する |
3.1 カレントディレクトリを取得、変更する方法(getcwd,chdir)
カレントディレクトリのパスを取得したあと、テストプログラムの引数に指定したパスにカレントディレクトリを変更するテストプログラムを作成します。
[root@server ~]# cat test.py #!/usr/bin/python3 import os dir = os.getcwd() print(dir) dir = input("ディレクトリ名を入力してください: ") os.chdir(dir) dir = os.getcwd() print(dir)
テストプログラムを実行すると、カレントディレクトリを表示したあと、指定したディレクトリにカレントディレクトリを変更したことがわかります。
[root@server ~]# ./test.py /root ディレクトリ名を入力してください: /var/log /var/log
3.2 ファイル一覧を取得する方法(listdir)
引数に指定したディレクトリのファイル一覧を表示するテストプログラムを作成します。
[root@server ~]# cat test.py #!/usr/bin/python3 import os dir = input("ディレクトリ名を入力してください: ") files = os.listdir(dir) print(files)
テストプログラムを実すると、/boot直下のファイルがリスト形式で表示されることがわかります。
[root@server ~]# ./test.py ディレクトリ名を入力してください: /boot ['efi', 'grub2', 'loader', 'vmlinuz-5.14.0-284.11.1.el9_2.x86_64', 'System.map-5.14.0-284.11.1.el9_2.x86_64', 'config-5.14.0-284.11.1.el9_2.x86_64', '.vmlinuz-5.14.0-284.11.1.el9_2.x86_64.hmac', 'symvers-5.14.0-284.11.1.el9_2.x86_64.gz', 'initramfs-5.14.0-284.11.1.el9_2.x86_64.img', 'vmlinuz-0-rescue-ae58d7b0f9374e8d801cd68b6296a573', 'initramfs-0-rescue-ae58d7b0f9374e8d801cd68b6296a573.img', 'initramfs-5.14.0-284.11.1.el9_2.x86_64kdump.img']
リスト形式ではなく、lsコマンドを実行した時のように表示するテストプログラムを作成します。
[root@server ~]# cat test.py #!/usr/bin/python3 import os dir = input("ディレクトリ名を入力してください: ") files = os.listdir(dir) for file in files: print(file)
テストプログラムを実行すると、/boot直下のファイルがlsコマンドを実行したときのように表示されることがわかります。
[root@server ~]# ./test.py ディレクトリ名を入力してください: /boot efi grub2 loader -snip-
3.3 ディレクトリのファイルを再帰的に表示する方法(walk)
テスト用のディレクトリ、ファイルを作成します。
[root@server ~]# mkdir -p dir1/dir2 [root@server ~]# touch dir1/file1.txt [root@server ~]# touch dir1/dir2/file2.txt
テストプログラムを作成します。
[root@server ~]# cat test.py #!/usr/bin/python3 import os for root, dirs, files in os.walk("dir1"): for dir in dirs: print("Directory:", os.path.join(root, dir)) for file in files: print("File:", os.path.join(root, file))
テストプログラムを実行します。
[root@server ~]# ./test.py Directory: dir1/dir2 File: dir1/file1.txt File: dir1/dir2/file2.txt
3.4 ディレクトリを作成・削除する方法(mkdir,rmdir)
引数に指定したディレクトリの作成、削除をするテストプログラムを作成します。指定したディレクトリが存在しなければ作成しますが、存在すれば作成しません。
[root@server ~]# cat test.py #!/usr/bin/python3 import os new_dir = input("ディレクトリ名を入力してください: ") if os.path.exists(new_dir): print(f"'{new_dir}' が存在するので、作成できません") else: print(f"'{new_dir}' を作成します ") os.mkdir(new_dir)
テストプログラムを実行します。初回実行時は/tmp/testが存在しないので、ディレクトリを作成できます。
[root@server ~]# ./test.py ディレクトリ名を入力してください: /tmp/test '/tmp/test' を作成します
2回目は/tmp/testが存在するので、ディレクトリが作成できないことがわかります。
[root@server ~]# ./test.py ディレクトリ名を入力してください: /tmp/test '/tmp/test' が存在するので、作成できません
3.5 ディレクトリを再帰的に作成する方法(makedirs)
[root@server ~]# cat test.py #!/usr/bin/python3 import os new_dir = input("ディレクトリ名を入力してください: ") if not os.path.exists(new_dir): os.makedirs(new_dir) print(f"'{new_dir}' を作成します ") else: print(f"'{new_dir}' が存在するので、作成できません")
[root@server ~]# ./test.py ディレクトリ名を入力してください: /tmp/dir1/dir2/dir3 '/tmp/dir1/dir2/dir3' を作成します
作成したディレクトリを確認します。/tmp直下にdir1/dir2/dir3が作成されていることがわかります。
[root@server ~]# ls -ld /tmp/dir1/dir2/dir3 drwxr-xr-x. 2 root root 6 9月 9 22:25 /tmp/dir1/dir2/dir3
3.6 ファイルやディレクトリの名前を変更する方法(rename)
renameはファイルやディレクトリの名前を変更する関数です。
[root@server ~]# cat test.py #!/usr/bin/python3 import os old_filename = input("ファイル名を入力してください: ") with open(old_filename, "w") as file: file.write("0123456789\n") with open(old_filename, "r") as file: old_data = file.read() print(f"作成したファイルの内容:{old_data}") new_filename = input("変更後のファイル名を入力してください: ") os.rename(old_filename, new_filename)
テストプログラムを実行します。
[root@server ~]# ./test.py ファイル名を入力してください: old.txt 作成したファイルの内容:0123456789 変更後のファイル名を入力してください: new.txt
[root@server ~]# cat new.txt 0123456789
4 os.pathモジュールの使い方
os.path モジュールはファイルパスやディレクトリパスを操作するための関数を提供するモジュールです。
関数 | 概要 |
---|---|
exists | ファイルやディレクトリが存在するかどうかを確認します |
dirname | ファイルパスからディレクトリ名を取得する |
basename | ファイルパスからファイル名を取得する |
splitext | ファイル名から拡張子を取り出します |
relpath | 相対パスを取得します |
abspath | 相対パスを絶対パスに変換します |
join | パスを結合します |
split | パス名からディレクトリ名とファイル名を取り出します |
4.1 ファイルやディレクトリの存在確認する方法(exitst)
引数に指定したディレクトリ名やファイル名が存在するかどうかを確認するテストプログラムを作成します。
[root@server ~]# cat test.py #!/usr/bin/python3 import os path = input("パス名を入力してください: ") if os.path.exists(path): print(f"{path} は存在します.") else: print(f"{path} は存在しません.")
ディレクトリの存在確認をしてみます。
[root@server ~]# ./test.py パス名を入力してください: /etc /etc は存在します.
ファイルの存在確認をしてみます。
[root@server ~]# ./test.py パス名を入力してください: /etc/chrony.conf /etc/chrony.conf は存在します.
4.2 パス名からディレクトリ名とファイル名を取り出す方法(dirname,basename)
dirnameはパス名からディレクトリ名を取り出す関数、basenameはパス名からファイル名を取り出す関数です。
[root@server ~]# cat test.py #!/usr/bin/python3 import os path = input("パス名を入力してください: ") dir = os.path.dirname(path) file = os.path.basename(path) print(f"dir={dir}, file={file}")
テストプログラムを実行します。パス名に/etc/chrony.confを指定すると、ディレクトリ名が/efc、ファイル名がchrony.confであることがわかります。
[root@server ~]# ./test.py パス名を入力してください: /etc/chrony.conf dir=/etc, file=chrony.conf
4.3 拡張子を取り出す方法(splitext)
拡張子を取りだすテストプログラムを実行します。
[root@server ~]# cat test.py #!/usr/bin/python3 import os path = input("パス名を入力してください: ") file_name, file_extension = os.path.splitext(path) print(f"ファイル名:{file_name}, 拡張子:{file_extension}")
chrony.confファイルの拡張子を確認します。拡張子がconfであることがわかります。
[root@server ~]# ./test.py パス名を入力してください: /etc/chrony.conf ファイル名:/etc/chrony, 拡張子:.conf
カーネルモジュールの拡張子を確認します。拡張子がxzであることがわかります
[root@server ~]# ./test.py パス名を入力してください: /usr/lib/modules/5.14.0-284.11.1.el9_2.x86_64/kernel/net/ipv4/ip_gre.ko.xz ファイル名:/usr/lib/modules/5.14.0-284.11.1.el9_2.x86_64/kernel/net/ipv4/ip_gre.ko, 拡張子:.xz
4.4 パス名からディレクトリ名とファイル名を求めるする方法(split)
[root@server ~]# cat test.py #!/usr/bin/python3 import os dir, file = os.path.split("/var/log/messages") print(f"dir={dir}, file={file}")
テストプログラムを実行すると、/var/log/messagesからディレクトリ名(/var/log)とファイ名(messages)がそれぞれ取得できていることがわかります。
[root@server ~]# ./test.py dir=/var/log, file=messages
4.5 パスを結合する方法(join)
joinメソッドは、引数で指定したパスを結合するメソッドです。この方法を使うと、ファイルシステムの階層構造に関する違いを気にせずにパスを作成できます。また、プラットフォーム間での互換性が確保されます。
joinメソッドの書式は以下のとおりです。
os.path.join("path1", "path2", "path3", ...)
"/"、"var"、"log”を結合するテストプログラムを作成します。
[root@server ~]# cat test.py #!/usr/bin/python3 import os log = os.path.join("/", "var", "log") print(log)
テストプログラムを実行すると、引数に指定したパスが結合されて/var/logと表示されることがわかります。
[root@server ~]# ./test.py /var/log
4.6 相対パス、絶対パスを求める方法(relpath,abspath)
テスト用のディレクトリを作成します。
[root@server ~]# mkdir dir1/dir2/dir3
テスト用に作成したディレクトリの相対パス、絶対パスを求めるテストプログラムを作成します。
[root@server ~]# cat test.py #!/usr/bin/python3 import os relative_path = "./dir1/dir2/dir3" absolute_path = os.path.abspath(relative_path) print(f"相対パス:{relative_path}, 絶対パス:{absolute_path}")
テストプログラムを実行すると、テスト用に作成したディレクトリの相対パス、絶対パスが表示されることがわかります。
[root@server ~]# ./test.py 相対パス:./dir1/dir2/dir3, 絶対パス:/root/dir1/dir2/dir3
5 ファイルオブジェクトの使い方
5.1 read系メソッド
5.1.1 ファイル全体を読み込む方法(read)
readメソッドは、ファイル全体または指定したバイト数を読み込むためのメソッドです。readメソッドを引数なしで呼び出すとファイル全体を読み込みます。readメソッドに引数を指定すると、指定したバイト数を読み出します。
ファイル全体を読み出すテストプログラムを作成します。
[root@server ~]# cat test.py #!/usr/bin/python3 with open("/tmp/test.txt", "r") as file: file_contents = file.read() print(file_contents)
テストプログラムが読み込むファイルを作成します。
[root@server ~]# vi /tmp/test.txt [root@server ~]# cat /tmp/test.txt 111 111 222 222 222
テストプログラムを実行すると、ファイル全体読み込んでいることがわかります。
[root@server ~]# ./test.py 111 111 222 222 222 [root@server ~]#
次は、readメソッドの引数に2を指定して、ファイルから2バイトを読み込むテストプログラムを作成します。
[root@server ~]# cat test.py #!/usr/bin/python3 with open("/tmp/test.txt", "r") as file: file_contents = file.read(2) print(file_contents)
テストプログラムを実行すると、ファイルから2バイト読み込んでいることがわかります。
[root@server ~]# ./test.py 11
5.1.2 ファイルから1行ずつ読み込む方法(readline)
readlineメソッドはファイルから1行ずつ読み込むためのメソッドです。ファイル終端に到達すると空文字を返します。
[root@server ~]# cat test.py #!/usr/bin/python3 with open("/tmp/test.txt", "r") as f: line = f.readline() while line: print(line, end="") line = f.readline()
テストプログラムを実行します。
[root@server ~]# ./test.py 111 111 222 222 222
5.1.3 1行をリスト形式で取得する方法(readlines)
readlinesメソッドはファイルから全ての行を一度に読み取り、各行を文字列のリストとして返すためのメソッドです。
[root@server ~]# cat test.py #!/usr/bin/python3 with open("/tmp/test.txt", "r") as f: lines = f.readlines() print(lines)
テストプログラムを実行します。
[root@server ~]# ./test.py ['111 111\n', '222 222 222\n']
5.2 write系メソッド
5.2.1 ファイルにデータを書き込む方法(write)
writeメソッドは、ファイルにデータを書き込むためのメソッドです。
引数に指定したファイルにデータを書き込むテストプログラムを作成します。
[root@server ~]# cat test.py #!/usr/bin/python3 file = input("ファイル名を入力してください: ") with open(file, "w") as file: file.write("0123456789\n")
テストプログラムを実行して、/tmp/sample.txtを作成してみます。
[root@server ~]# ./test.py ファイル名を入力してください: /tmp/sample.txt
作成したファイルの中身を確認します。
[root@server ~]# cat /tmp/sample.txt 0123456789
5.3 seekメソッド
seekメソッドは、ファイルオブジェクト内のカーソル位置を移動するためのメソッドです。書式は以下の通りす。
seek(offset, whence)
引数 | 意味 |
offset | 移動するバイト数を指定します。正の整数値はファイルの先頭から移動し、負の整数値はファイルの末尾から逆方向に移動します |
whence | デフォルトは0でファイルの先頭からの相対位置を示します。1は現在の位置からの相対位置を示し、2はファイルの末尾からの相対位置を示します |
テストプログラムを作成します。
[root@server ~]# cat test.py #!/usr/bin/python3 seek = int(input("移動するバイト数を入力してください: ")) byte = int(input("読み込むバイト数を入力してください: ")) with open("/tmp/test.txt", "r") as f: f.seek(seek) data = f.read(byte) print(data)
テストプログラムが読み込むファイルを作成します。
[root@server ~]# vi /tmp/test.txt [root@server ~]# cat /tmp/test.txt 0123456789
ファイル先頭から2バイト読み出してみます。
[root@server ~]# ./test.py 移動するバイト数を入力してください: 0 読み込むバイト数を入力してください: 2 01
ファイル先頭から1バイト移動してから5バイト読み出してみます。
[root@server ~]# ./test.py 移動するバイト数を入力してください: 1 読み込むバイト数を入力してください: 5 12345
Y 参考図書
TECHNICAL MASTER はじめてのAlmaLinux 9 & Rocky Linux 9 Linuxサーバエンジニア入門編
Z 参考情報
私が業務や記事執筆で参考にした書籍を以下のページに記載します。
Linux技術のスキルアップをしよう! - hana_shinのLinux技術ブログ
記事作成に参考にした書籍です。
- Pythonコードレシピ集
サンプルコードが短く、分かりやすいです。
Pythonコードレシピ集(Kindle版)
- スッキリわかるPython入門 (スッキリわかる入門シリーズ)
簡潔な説明で分かりやすいです。
スッキリわかるPython入門 (スッキリわかる入門シリーズ)(単行本)
スッキリわかるPython入門 (スッキリわかるシリーズ)(Kindle版)