【问题标题】:File Manipulation: Scripting Question文件操作:脚本问题
【发布时间】:2011-04-14 09:03:43
【问题描述】:

我有一个脚本,它连接到数据库并获取所有满足查询的记录。这些记录结果是服务器上存在的文件,所以现在我有一个包含所有文件名的文本文件。

我想要一个知道的脚本:

  1. output.txt 文件中每个文件的大小是多少?
  2. 该文本文件中所有文件的总大小是多少?

更新: 我想知道如何使用Perl programming language 完成我的任务,任何输入将不胜感激。

注意:我没有任何特定的语言限制,它可以是 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. 执行步骤 1 后,如何删除 output.txt 文件中的所有文件?

任何建议将不胜感激。

【问题讨论】:

  • 如果文件名中有空格,则必须引用文件名os.system('du -h "%s"' % fullpath)
  • 投反对票通常有解释,请提供一个,以便我改进问题。
  • @RickF:我尝试过使用你建议的 du 命令,但它给了我一些数字,我该如何解释它,是 kb、mb、gb 还是 by ?另外我的操作系统版本很旧,所以我没有 du -h 选项,有没有办法可以使用命令 my ($size) = split(' ', du "$folderpath/$_"); ?

标签: python perl file unix scripting


【解决方案1】:

在 perl 中,-s filetest 运算符很可能是您想要的。

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";

请注意,-sbytes 为单位给出大小,而不是像 du 这样的 blocks

进一步调查,perl 的-s 等同于du -b。您可能应该阅读特定 du 上的手册页,以确保您实际测量的是您打算测量的内容。

如果您真的想要 du 值,请将上面的 $size 赋值更改为:

my ($size) = split(' ', `du "$folderpath/$_"`);

【讨论】:

  • @RickF:这是给出文件夹中每个文件的大小加上文件夹中文件的总大小吗?
  • @RickF: 有没有一种方法可以获得块大小而不是使用du 获得的字节大小?
  • 在我的 Linux 机器上,块大小为 1024 字节 (1kb),因此您只需将 $size 除以它。
  • 实际上,在进一步的测试中,du -h 为我系统上的任何文件返回至少 '4.0k',即使 ls 或 perl -s 显示的大小小于该值。
  • 实际上,du 总是假设一个块为 512 字节,即使您的块大小不同。单一 UNIX 规范的一部分 en.wikipedia.org/wiki/Du_(Unix)
【解决方案2】:

目瞪口呆,你可以让你的脚本这样工作:

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)

然后您可以通过./script.py ft.txt 执行脚本(在chmod +x [script_name].py 之后),然后它将使用命令行文件的路径作为文件“ft.txt”的假定路径。您也可以处理多个文件。

【讨论】:

  • 我尝试了你的方法,当我尝试添加文件时,我得到像315904L 这样的值,不确定L 代表什么?另外,如果我运行第一个脚本,那么它给我的大小为86K259K,如果我在 Calc 上执行,总共给我345K,所以不确定,但我们在两个数字的总和上得到不同的数字不同的方式,对此有什么想法吗?
  • 因为你的文件真的很大,对吧?让我将脚本更改为使用块而不是像 du 那样使用字节......
  • 我没有看到脚本有任何变化,这里的块是什么意思?
  • 建议:我很困惑我应该接受谁的答案,RickF 或 drawk 都解决了我的问题,有什么建议吗?
【解决方案3】:

您可以在自己的 shell 脚本中执行此操作。

您在假脱机文件output.txt 中拥有所有文件名,您只需在现有脚本末尾添加:

< output.txt  du -h

它会给出每个文件的大小以及最后的总和。

【讨论】:

  • @codaddict:在 output.txt du -h 命令之前,我不明白&lt; 上的工作,你能解释一下吗?
  • du -h &lt; output.txt
  • 我应该在哪里添加这个,除了第一个脚本中的假脱机命令?
  • 但是从 sql 我只是获取文件名而不是文件所在的实际文件夹位置,我正在传递 python 脚本,所以不确定它是如何工作的?
  • 这不起作用 - du 不接受管道参数。可能有办法让它工作,但正如所写的那样,它不起作用。
【解决方案4】:

您可以使用您绘制的 Python 框架并添加 os.path.getsize(fullpath) 来获取单个文件的大小。

例如,如果您想要一个包含文件名和大小的字典,您可以:

dict((f, os.path.getsize(f)) for f in file)

请记住,os.path.getsize(...) 的结果以字节为单位,因此如果需要,您必须将其转换为其他单位。

一般os.path是操作文件和路径的关键模块。

【讨论】:

  • 我已在上述问题的更新中添加了脚本,但仍然出现标准错误。
  • 我已根据您的建议和所面临的问题,使用最新脚本更新了问题。
  • 我已经更新了您的回复的答案以及使用该方法出现的错误。
  • 在这种情况下,列表推导是多余的,一个简单的生成器表达式就可以了,而且效率更高。只需留下方括号。
  • 你能详细说明一下吗,我也更新了我的问题,具体回答了这个答案,你能分享你的cmets吗。
猜你喜欢
  • 1970-01-01
  • 2011-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-18
  • 2023-04-01
  • 2021-02-13
相关资源
最近更新 更多