文件操作:脚本问题
我有一个脚本,它可以连接到数据库并获取所有符合条件的记录。这些记录的结果是服务器上的文件,所以现在我有一个文本文件,里面列出了所有的文件名。
我想要一个脚本,能够知道:
output.txt
文件中每个文件的大小是多少?- 这些文件的总大小是多少?
更新:我想知道如何使用Perl编程语言
来完成我的任务,任何建议都非常感谢。
注意:我没有特定的语言限制,可以使用Perl或Python脚本,我可以从Unix命令行运行。目前我在使用bash shell,并且有sh
和py
脚本。这个怎么做呢?
我的脚本:
#!/usr/bin/ksh
export ORACLE_HOME=database specific details
export PATH=$ORACLE_HOME/bin:path information
sqlplus database server information<<EOF
SET HEADING OFF
SET ECHO OFF
SET PAGESIZE 0
SET LINESIZE 1000
SPOOL output.txt
select * from my table_name;
SPOOL OFF
EOF
我知道du -h
是我应该使用的命令,但我不太确定我的脚本应该怎么写,我在Python中尝试过一些东西。我对Python完全是新手,这是我第一次尝试。
这是我写的:
import os
folderpath='folder_path'
file=open('output file which has all listing of query result','r')
for line in file:
filename=line.strip()
filename=filename.replace(' ', '\ ')
fullpath=folderpath+filename
# print (fullpath)
os.system('du -h '+fullpath)
输出文本文件中的文件名例如是:007_009_Bond Is Here_009_Yippie.doc
任何指导都将非常感谢。
更新:
- 如何使用
Perl
将output.txt
文件中列出的所有文件移动到其他文件夹? - 完成第一步后,如何删除
output.txt
文件中列出的所有文件?
任何建议都将非常感谢。
4 个回答
你可以直接在你的脚本里实现这个功能。
你所有的文件名都在一个叫 output.txt
的文件里,你只需要在现有的脚本最后加上以下内容:
< output.txt du -h
这样做会显示每个文件的大小,并在最后给出一个总大小。
大致上,你可以让你的脚本这样工作:
1) 删除这一行 filename=filename.replace(' ', '\ ')
。转义字符比这复杂,你应该直接把完整路径用引号括起来,或者使用一个Python库来根据具体的操作系统来处理它;
2) 你可能在路径和文件名之间缺少一个分隔符;
3) 在调用os.system的时候,你需要在完整路径周围加上单引号。
这个方法对我有效:
#!/usr/bin/python
import os
folderpath='/Users/andrew/bin'
file=open('ft.txt','r')
for line in file:
filename=line.strip()
fullpath=folderpath+"/"+filename
os.system('du -h '+"'"+fullpath+"'")
文件“ft.txt”里面的文件名没有路径,而路径部分是 '/Users/andrew/bin'
。其中一些文件的名字需要转义,但用单引号把文件名括起来就解决了这个问题。
这会对.txt文件中的每个文件运行 du -h
,但不会给你总数。在Perl或Python中,这个操作相对简单。
这里有一个基于你代码的Python脚本来实现这个功能:
#!/usr/bin/python
import os
folderpath='/Users/andrew/bin/testdir'
file=open('/Users/andrew/bin/testdir/ft.txt','r')
blocks=0
i=0
template='%d total files in %d blocks using %d KB\n'
for line in file:
i+=1
filename=line.strip()
fullpath=folderpath+"/"+filename
if(os.path.exists(fullpath)):
info=os.stat(fullpath)
blocks+=info.st_blocks
print `info.st_blocks`+"\t"+fullpath
else:
print '"'+fullpath+"'"+" not found"
print `blocks`+"\tTotal"
print " "+template % (i,blocks,blocks*512/1024)
注意这次你不需要给文件名加引号或转义;Python会帮你处理。这个脚本使用分配块来计算文件大小;和du的计算方式一样。如果我对和ft.txt
中列出的相同文件运行 du -ahc
,我会得到相同的数字(其实有点差别;du
报告的是 25M
,而我得到的是 24324 KB
),但它报告的块数是一样的。(顺便说一句:“块”在Unix下总是被认为是512字节,尽管在更大磁盘上的实际块大小通常更大。)
最后,你可能想考虑让你的脚本能够读取命令行中的一组文件,而不是在脚本中硬编码文件和路径。考虑一下:
#!/usr/bin/python
import os, sys
total_blocks=0
total_files=0
template='%d total files in %d blocks using %d KB\n'
print
for arg in sys.argv[1:]:
print "processing: "+arg
blocks=0
i=0
file=open(arg,'r')
for line in file:
abspath=os.path.abspath(arg)
folderpath=os.path.dirname(abspath)
i+=1
filename=line.strip()
fullpath=folderpath+"/"+filename
if(os.path.exists(fullpath)):
info=os.stat(fullpath)
blocks+=info.st_blocks
print `info.st_blocks`+"\t"+fullpath
else:
print '"'+fullpath+"'"+" not found"
print "\t"+template % (i,blocks,blocks*512/1024)
total_blocks+=blocks
total_files+=i
print template % (total_files,total_blocks,total_blocks*512/1024)
然后你可以通过 chmod +x [script_name].py
来执行脚本,再用 ./script.py ft.txt
来运行,这样它就会把命令行文件的路径当作“ft.txt”文件的默认路径。你也可以处理多个文件。
在perl中,-s
这个文件测试操作符可能正是你需要的。
use strict;
use warnings;
use File::Copy;
my $folderpath = 'the_path';
my $destination = 'path/to/destination/directory';
open my $IN, '<', 'path/to/infile';
my $total;
while (<$IN>) {
chomp;
my $size = -s "$folderpath/$_";
print "$_ => $size\n";
$total += $size;
move("$folderpath/$_", "$destination/$_") or die "Error when moving: $!";
}
print "Total => $total\n";
需要注意的是,-s
给出的大小是以字节为单位,而不是像du
那样以块为单位。
经过进一步调查,perl的-s
相当于du -b
。你可能需要查看一下你具体的du
手册,确保你测量的内容是你想要的。
如果你真的想要du
的值,可以把上面$size
的赋值改成:
my ($size) = split(' ', `du "$folderpath/$_"`);