http://www.perlmonks.org?node_id=991424

msx has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, Hoping someone could enlighen me. I have a file containing lines which consists of filenames and directories. I need to strip all empty directory entries in this file. Below is an example of the file contents: Filname is filelist.txt
:BOF /peter/john/lilly.pdf /john/peter/jill.pdf /jimmy/gill/ /wilbur/yankee/ /lola/riley/jibmo.txt /rolly/polly/quebe.lst :EOF
I'm trying in vain to remove all lines ending with the / char. Note there could be any number of lines ending with / and they could be anywhere in the file. Any wisdom will be greatly appreciated.

Replies are listed 'Best First'.
Re: remove lines from file ending with / char
by swampyankee (Parson) on Sep 03, 2012 at 13:23 UTC

    The first place to look is in perlfaq5. Anyhow, there are several ways to do it. The easiest is to

    (((pseudocode))) open, for reading, the file you want to change (input file) open, for writing, a temp file. until EOF { read a record from the input file. if you want to keep it write it to the temp file } replace the input file with the temp file

    If the file is small (ymmv), you can do something like this:

    (((pseudocode))) open input file for reading slurp ENTIRE input file into array (@contents = <INFILE>) close the input file use grep to remove lines with trailing slashes from the array (@conten +ts = grep { !/\/$/ } @contents) open the input file for writing (this act will destroy the input file! +) write array into the file

    A couple of suggestions: first, test from a copy of the file you plan on doing this to. Second, study perlre and grep for hints. Third, beware of trailing white space.


    Information about American English usage here and here. Floating point issues? Please read this before posting. — emc

Re: remove lines from file ending with / char
by choroba (Cardinal) on Sep 03, 2012 at 13:14 UTC
    Please, give us more information: Is it possible for a directory to be mentioned once with no content, but later with a file, like this?
    /foo/bar/ /foo/bar/baz
    Or only the "empty" directories can be listed without files. If so, you can just use
    grep { 0 != index reverse($_), '/' } @files
    or
    grep !m{/$}, @files
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: remove lines from file ending with / char
by BillKSmith (Monsignor) on Sep 03, 2012 at 19:01 UTC

    This task can be done with a one-liner. Refer to the runtime options /e, /i, and /p in perldoc perlrun.

    Bill
Re: remove lines from file ending with / char
by philiprbrenan (Monk) on Sep 06, 2012 at 00:13 UTC

    Just supposing the problem was to find the smallest set of directories whose removal would not delete any files (the folded comments make it more difficult to read):

    use feature ":5.14"; use warnings FATAL => qw(all); use strict; use Data::Dump qw(dump pp); sub findEmptyDirectories(&@) {package FindEmptyDirectories; my $R = shift; # Processing routine from us +er followed by file/directory names my $d = {}; # Simulated directory tree {for(@_) # Load directory tree with e +ach file {if (my @c = /([^\/]+)/g) # Get path components from f +ile name {my $f = pop @c unless /\/\Z/; # Get file name unless direc +tory my $c = $d; # Start of descent through d +irectory tree $c = $c->{dir}{$_} //= {} for @c; # Descend along each path co +mponent adding new nodes as necessary $c->{file}{$f}++ if defined $f; # Count files at this level +with this name } } } sub R($) # Descend tree to count file +s in each directory {my ($d) = @_; # Position in directory tree $d->{files} += &R($d->{dir}{$_}) for keys %{$d->{dir}}; # Count fi +les below this level $d->{files} += keys %{$d->{file}}; # plus files at this level } R($d); # Count files at each level sub r($$$) # Descend tree in in-order i +n order to perform user action on empty directories {my ($R, $d, $p) = @_; # User action, directory sub + tree, path to sub tree return $R->(@$p) unless $d->{files}; # No files below this direct +ory so perform user action and return &r($R, $d->{dir}{$_}, [@$p, $_]) for sort keys %{$d->{dir}}; # Els +e process lower levels in directory tree } r($R, $d, []); # Call user action on direct +ories with no files } findEmptyDirectories {say "/", join("/", @_), "/"} split /\n/, << 'END +'; /peter/john/lilly.pdf /john/peter/jill.pdf /jimmy/gill/a.txt /jimmy/gill/johnny/ /wilbur/yankee/ /wilbur/yankee/aaa/bbb/nnn/ /wilbur/yankee/aaa/ccc/nnn/ /wilbur/yankee/aaa/ccc/aaa.txt /lola/riley/jibmo/txt /lola/riley/jibmo.txt /rolly/polly/quebe.lst END

    Produces:

    /jimmy/gill/johnny/ /wilbur/yankee/aaa/bbb/ /wilbur/yankee/aaa/ccc/nnn/