本題通りの内容です。
Pythonでファイルを移動する場合はこのいずれかを利用すると思いますが、挙動がまるで違うので、それに気を付けないとエラーを頻発することになります。
ケース1:ファイル名まで明示的に記述して移動する
shutil.move
まずshutilとはshとutilをくっつけた造語で、shell utilityのことです。shellとはざっくり言ってCUIなどを使って人為的にコンピュータに命令を送ることであり、つまりmove(移動)に対するユーティリティということです。
それを踏まえ、このshutil.moveとはファイルを移動させるコマンドであり、それ以上でもそれ以下でもありません。したがって、存在しないフォルダは自動的に生成できないのです。
また、すでに存在しているファイルは自動で上書きされます。
import shutil, os
org_path = os.path.join("tests","test.py")
moved_path = os.path.join("tests2","test.py")
shutil.move(org_path, moved_path)
※tests2フォルダが存在しない場合は、unknown file or directoryとエラーを返す。
os.rename
対するos.renameとはWindowsのOSそのものを操作するコマンドの一つであり、これはファイルを移動させているのではなく、ファイルの参照パスそのものを書き換えているのです。したがって、先程と同じような動作を実施した場合、仮にtest2フォルダが未作成であっても、自動で作ってくれます。
ただし、パス構造の書き換えというのが厄介なポイントで、移動元のフォルダが空になった場合、そのディレクトリは存在しないものとして空フォルダを自動消去してしまう挙動が発生します(shutil.moveはファイルだけの移動なので空フォルダは残ります)。
また、移動先に同じファイルが存在している場合は書き換え不可なので、処理エラーとなります。
import shutil, os
org_path = os.path.join("tests","test.py")
moved_path = os.path.join("tests2","test.py")
os.rename(org_path, moved_path)
※厳密に言えば、testsフォルダをtests2フォルダに書き換えてしまう。