shutil
(或称为 shell
工具)模块中包含一些函数,在Python程序中复制、移动、改名和删除文件。
要使用 shutil
的函数,首先需要 import shutil
。
复制文件和文件夹
shutil
模块提供了一些函数,用于复制文件和整个文件夹。
调用 shutil.copy(source,destination)
,
将路径 source
处的文件复制到路径 destination
处的文件夹( source
和 destination
都是字符串)。
如果 destination
是一个文件名,它将作为被复制文件的新名字。
该函数返回一个字符串,表示被复制文件的路径。
在交互式环境中输入以下代码,看看 shutil.copy()
的效果:
!ls /etc/
alternatives gss networks selinux apt host.conf nsswitch.conf services bash.bashrc hostname opt shadow bash_completion.d hosts os-release shadow- bindresvport.blacklist init.d pam.conf shells ca-certificates issue pam.d skel ca-certificates.conf issue.net passwd ssl cloud jupyter passwd- subgid cron.d kernel perl subgid- cron.daily ld.so.cache profile subuid debconf.conf ld.so.conf profile.d subuid- debian_version ld.so.conf.d protocols sudo.conf default legal rc0.d sudo_logsrvd.conf dpkg libaudit.conf rc1.d sudoers e2scrub.conf locale.alias rc2.d sudoers.bak environment locale.conf rc3.d sudoers.d ethertypes locale.gen rc4.d sysctl.conf fstab localtime rc5.d sysctl.d gai.conf login.defs rc6.d systemd gnutls logrotate.d rcS.d terminfo group lsb-release resolv.conf timezone group- machine-id rmt update-motd.d gshadow mke2fs.conf rpc wgetrc gshadow- mtab security xattr.conf
import shutil, os
shutil.copy('/etc/os-release','/tmp')
'/tmp/os-release'
shutil.copy('./xx_chapter.ipynb','/tmp/xx_new_chapter.ipynb')
'/tmp/xx_new_chapter.ipynb'
第一个 shutil.copy()
调用将文件 复制到文件夹C:\delicious
。返回值是刚刚被复制的文件的路径。
请注意,因为指定了一个文件夹作为目的地,
原来的文件名 spam.txt
就被用作新复制的文件名。
第二个 shutil.copy()
调用也将文件C:\eggs.txt
复制到文件夹C:\delicious
,
但为新文件提供了一个名字 eggs2.txt
。
shutil.copy()
将复制一个文件,shutil.copytree()
将复制整个文件夹,以及它包含的文件夹和文件。
调用 shutil.copytree(source,destination)
,将路径 source
处的文件夹,
包括它的所有文件和子文件夹,复制到路径 destination
处的文件夹。
source
和 destination
参数都是字符串。该函数返回一个字符串,是新复制的文件夹的路径。
在交互式环境中输入以下代码:
if os.path.exists('/tmp/dest_backup')==False:
shutil.copytree('./', '/tmp/dest_backup')
dest_dir = '/tmp/xx_dst'
if os.path.exists(dest_dir):
pass
else:
os.mkdir(dest_dir)
shutil.move('/tmp/xx_new_chapter.ipynb', '/tmp/xx_dst')
'/tmp/xx_dst/xx_new_chapter.ipynb'
假定在 /tmp
目录中已存在一个名为 dst
的文件夹,
shutil.move()
调用是将目标文件移动到文件夹 /tmp/dst
中。
如果在 /tmp/dst
中原来已经存在一个文件 new_chapter.ipynb
,它就会被覆写。
因为用这种方式很容易不小心覆写文件,所以在使用 move()
时应该注意。
destination
路径也可以指定一个文件名。
在下面的例子中,source
文件被移动并改名。
shutil.move('/tmp/xx_dst/xx_new_chapter.ipynb','/tmp/xx_dst/xx_new_chapter_2.ipynb')
'/tmp/xx_dst/xx_new_chapter_2.ipynb'
这一行是说,“将C:\bacon.txt
移动到文件夹C:\eggs
,
完成之后,将 bacon.txt
文件改名为 new_bacon.txt
。”
前面两个例子都假设在C:\目录下有一个文件夹eggs。
但是如果没有 eggs
文件夹, move()
就会将
bacon.txt
改名,变成名为 eggs
的文件。
from pathlib import Path
my_fies = Path("chd3_test/hello.txt")
if my_fies.is_file():
shutil.move('/home/shaopp/jubook/chd3_test/hello.txt', '/home/shaopp/jubook/chd3_test/eggs')
这里, move()
在C:\目录下找不到名为eggs的文件夹,
所以假定destination
指的是一个文件,而非文件夹。
所以 bacon.txt
文本文件被改名为 eggs(没有.txt
文件扩展名的文本文件),
这可能是程序中很难发现的缺陷,
因为 move()
调用会很开心地做一些事情,
但和所期望的完全不同。这也是在使用 move()
时要小心的另一个理由。
最后,构成目的地的文件夹必须己经存在, 否则 Python 会抛出异常。
永久删除文件和文件夹
利用 os
模块中的函数,
可以删除一个文件或一个空文件夹。
但利用 shutil
模块,
可以删除一个文件夹及其所有的内容。
- 用
os.unlink(path)
将删除path
处的文件。 - 调用
os.rmdir(path)
将删除path
处的文件夹。该文件夹必须为空,其中没有任何文件和文件夹。 - 调用
shutil.rmtree(path)
将删除path
处的文件夹,
它包含的所有文件和文件夹都会被删除。
在程序中使用这些函数时要小心!可以第一次运行程序时,
注释掉这些调用,并且加上 print()
调用,
显示会被删除的文件。这样做是一个好主意。
下面有一个Python程序,本来打算删除具有
.txt
扩展名的文件,但有一处录入错误(用粗体突出显示),
结果导致它删除了 .rxt
文件。
import os
os.chdir('/home/shaopp/jubook/chd3_test')
for filename in os.listdir():
if filename.endswith('.txt'):
os.unlink(filename)
如果有某些重要的文件以 .rxt
结尾,它们就会被不小心永久地删除。
作为替代,应该先运行像这样的程序:
import os
for filename in os.listdir('/home/shaopp/jubook/chd3_test'):
if filename.endswith('.txt'):
#os.unlink(filename)
print(filename)
现在 os.unlink()
调用被注释掉,所以Python会忽略它。
作为替代,会打印出将被删除的文件名。
先运行这个版本的程序,就会知道,不小心告诉程序要删除 .rxt
文件,
而不是 .txt
文件。
在确定程序按照自己的意图工作后,删除 print(filename)
代码行,
取消 os.imlink(filename)
代码行的注释。然后再次运行该程序,实际删除这些文件。
send2trash
模块安全删除
因为Python内建的 shutil.rmtree()
函数不可恢复地删除文件和文件夹,所以用起来可能有危险。
删除文件和文件夹的更好方法,
是使用第三方的 send2trash
模块。
可以在终端窗口中运行如下命令安装该模块。
sudo apt install -y python3-send2trash
或
pip install send2trash
Requirement already satisfied: send2trash in /opt/conda/lib/python3.12/site-packages (1.8.3) Note: you may need to restart the kernel to use updated packages.
利用 send2trash
,比Python常规的删除函数要安全得多,
因为它会将文件夹和文件发送到计算机的垃圾箱或回收站,而不是永久删除它们。
如果因程序缺陷而用send2trash
删除了某些不想删除的东西,稍后可以从垃圾箱恢复。
安装 send2trash
后,在交互式环境中输入以下代码:
import send2trash
baconFile = open('xx_bacon.txt', 'a') #creates the file
baconFile.write('Bacon is not a vegetable.')
25
baconFile.close()
send2trash.send2trash('xx_bacon.txt')
一般来说,总是应该使用 send2trash.send2trash()
函数来删除文件和文件夹。
虽然它将文件发送到垃圾箱,
让稍后能够恢复它们,但是这不像永久删除文件,
不会释放磁盘空间。如果希望程序释放磁盘空间,
就要用 os
和 shutil
来删除文件和文件夹。
请注意, send2trash()
函数只能将文件送到垃圾箱,
不能从中恢复文件。