文件操作:脚本问题

3 投票
4 回答
904 浏览
提问于 2025-04-16 04:20

我有一个脚本,它可以连接到数据库并获取所有符合条件的记录。这些记录的结果是服务器上的文件,所以现在我有一个文本文件,里面列出了所有的文件名。

我想要一个脚本,能够知道:

  1. output.txt文件中每个文件的大小是多少?
  2. 这些文件的总大小是多少?

更新:我想知道如何使用Perl编程语言来完成我的任务,任何建议都非常感谢。

注意:我没有特定的语言限制,可以使用Perl或Python脚本,我可以从Unix命令行运行。目前我在使用bash shell,并且有shpy脚本。这个怎么做呢?

我的脚本:

#!/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

任何指导都将非常感谢。

更新:

  1. 如何使用Perloutput.txt文件中列出的所有文件移动到其他文件夹?
  2. 完成第一步后,如何删除output.txt文件中列出的所有文件?

任何建议都将非常感谢。

4 个回答

0

你可以直接在你的脚本里实现这个功能。

你所有的文件名都在一个叫 output.txt 的文件里,你只需要在现有的脚本最后加上以下内容:

< output.txt  du -h

这样做会显示每个文件的大小,并在最后给出一个总大小。

1

大致上,你可以让你的脚本这样工作:

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”文件的默认路径。你也可以处理多个文件。

1

在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/$_"`);

撰写回答