いくつかの基本的なコードを使用してフォルダーを読み取り、フォルダーにあるファイルの数を通知するプログラムを作成したいと思います。これが私が現在それをしている方法です:
import os
folders = ['Y:\\path1', 'Y:\\path2', 'Y:\\path3']
for stuff in folders:
for root, dirs, files in os.walk(stuff, topdown=True):
print("there are", len(files), "files in", root)
これは、「メイン」フォルダー内に複数のフォルダーができるまではうまく機能します。これは、フォルダー/ファイル管理が不十分なために、ファイルの長いジャンクリストが返される可能性があるためです。ですから、せいぜい二級だけに行きたいです。例:
Main Folder
---file_i_want
---file_i_want
---Sub_Folder
------file_i_want <--*
------file_i want <--*
------Sub_Folder_2
---------file_i_dont_want
---------file_i_dont_want
break
およびdel dirs[:]
を この投稿 および この投稿 から取得して、最初のレベルのみに移動する方法を知っています。
import os
import pandas as pd
folders = ['Y:\\path1', 'Y:\\path2', 'Y:\\path3']
for stuff in folders:
for root, dirs, files in os.walk(stuff, topdown=True):
print("there are", len(files), "files in", root)
del dirs[:] # or a break here. does the same thing.
しかし、どのように検索しても、2層の深さを調べる方法はわかりません。私はそれに関する何か他の投稿を理解していないだけかもしれませんか? del dirs[:2]
のようなものを考えていましたが、役に立ちませんでした。誰かが私を案内したり、これを達成する方法を説明したりできますか?
あなたはこのようにすることができます:
_depth = 2
# [1] abspath() already acts as normpath() to remove trailing os.sep
#, and we need ensures trailing os.sep not exists to make slicing accurate.
# [2] abspath() also make /../ and ////, "." get resolved even though os.walk can returns it literally.
# [3] expanduser() expands ~
# [4] expandvars() expands $HOME
stuff = os.path.abspath(os.path.expanduser(os.path.expandvars(stuff)))
for root,dirs,files in os.walk(stuff):
if root[len(stuff):].count(os.sep) < depth:
for f in files:
print(os.path.join(root,f))
_
キーは:if root[len(stuff):].count(os.sep) < depth
これはstuff
をroot
から削除するため、結果はstuff
に対して相対的です。ファイルセパレータの数を数えるだけです。
深さはLinuxのfind
コマンドのように機能します。つまり、_-maxdepth 0
_は何もしないことを意味し、_-maxdepth 1
_は最初のレベルのファイルのみをスキャンし、サブディレクトリに含まれる_-maxdepth 2
_ファイルをスキャンします。
もちろん、それでも完全なファイル構造がスキャンされますが、非常に深くない場合は機能します。
別の解決策は、最大の再帰レベルで_os.listdir
_を再帰的に(ディレクトリチェック付きで)のみ使用することですが、必要がない場合は少しトリッキーです。それほど難しくないので、ここに1つの実装を示します。
_def scanrec(root):
rval = []
def do_scan(start_dir,output,depth=0):
for f in os.listdir(start_dir):
ff = os.path.join(start_dir,f)
if os.path.isdir(ff):
if depth<2:
do_scan(ff,output,depth+1)
else:
output.append(ff)
do_scan(root,rval,0)
return rval
print(scanrec(stuff)) # prints the list of files not below 2 deep
_
注:_os.listdir
_および_os.path.isfile
_は2つのstat
呼び出しを実行するため、最適ではありません。 Python 3.5では、_os.scandir
_を使用すると、その二重呼び出しを回避できます。
セパレータを数えることができ、それが2レベルの深さである場合は、dirs
の内容を削除して、walk
が深く再帰しないようにします。
import os
MAX_DEPTH = 2
folders = ['Y:\\path1', 'Y:\\path2', 'Y:\\path3']
for stuff in folders:
for root, dirs, files in os.walk(stuff, topdown=True):
print("there are", len(files), "files in", root)
if root.count(os.sep) - stuff.count(os.sep) == MAX_DEPTH - 1:
del dirs[:]
Pythonドキュメント 動作について次のように述べています。
TopdownがTrueの場合、呼び出し元はdirnamesリストをインプレースで(おそらくdelまたはslice割り当てを使用して)変更でき、walk()はdirnamesに名前が残っているサブディレクトリにのみ再帰します。これを使用して、検索を整理したり、特定の訪問順序を課したり、呼び出し元が作成したディレクトリや、名前を変更したりしてwalk()を再開する前にwalk()に通知したりすることもできます。
folders
にあるセパレータを考慮する必要があることに注意してください。たとえば、y:\path1
は、ルートはy:\path
しかし、そこで再帰を停止したくありません。