Frage

I’m trying to check my folder for files that are empty (0 bytes). I have about 1,200 files so Perl will make this task very easy :)

Here is my code so far but it doesn't seem to work. (It’s just listing all of the files.) Can anyone teach me what I’ve done wrong? Thanks!

#!/usr/bin/perl
@files = glob('*');
if ((-s @files) == 0) {
    print"@files\n";
}
War es hilfreich?

Lösung 2

#!/usr/bin/perl

use strict; use warnings;

foreach my $file (glob('*')) {
    unless (-s $file) {
        print "$file\n";
    }
}

Andere Tipps

You do one check, yet you have multiple files. Obviously, that makes no sense. You need to add a loop to check each file.

#!/usr/bin/perl
use strict;
use warnings;
my @files = grep { -s $_ == 0 } glob('*');
   # or:    grep { ! -s $_ }
   # or:    grep { -z $_ }
   # or:    grep { -z }
   # or:    grep -z,
print "@files\n";

In your version, you are attempting to get the size of the file named 12 or whatever the number of elements of @files is. As a result, -s was returning undef with $!{ENOENT} set.

yet another way of doing things in perl

use File::stat;   
foreach (glob('*')){ 
   print stat($_)->size,"\n"
};     

# this will file sizes of all files and directories 
# you need to check if its a file and if size is zero

I recommend a solution much like all the others, but I recomment that you use the -z operator rather than the -s operator.

In my mind, it is clearer to code "if the file is zero length" as opposed to "unless the file has non-zero length"

Both have the same boolean meaning, but the former codes your intent more clearly. Otherwise, the answers you've been getting are all pretty good.

 #/run/my/perl

 use strict;
 use warnings;
 foreach my $file ( glob("*") ) {
   print "$file\n" if -z $file;
 }

To see how it is done when searching all levels beneath the current directory, consider the output of the standard tool find2perl.

$ find2perl . -type f -size 0c
#! /usr/bin/perl -w
    eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
        if 0; #$running_under_some_shell

use strict;
use File::Find ();

# Set the variable $File::Find::dont_use_nlink if you're using AFS,
# since AFS cheats.

# for the convenience of &wanted calls, including -eval statements:
use vars qw/*name *dir *prune/;
*name   = *File::Find::name;
*dir    = *File::Find::dir;
*prune  = *File::Find::prune;

sub wanted;

# Traverse desired filesystems
File::Find::find({wanted => \&wanted}, '.');
exit;

sub wanted {
    my ($dev,$ino,$mode,$nlink,$uid,$gid);

    (($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) &&
    -f _ &&
    (int(-s _) == 0)
    && print("$name\n");
}

Run the code above with

$ find2perl . -type f -size 0c | perl

Adapting this knowledge to your situation

my @files = grep -f $_ && -s _ == 0, glob "*";
print @files, "\n";

or in a single call to print with

print +(grep -f $_ && -z _, <*>), "\n";

Using the special _ filehandle that holds a cached copy of the most recent stat result avoids making two traps into the operating system where one will suffice. Note the extra check that the file is a plain file (-f) that is necessary because the zero-size check—either -s _ == 0 or -z _—will return true for empty directories on some filesystems.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top