Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Onliner magic to remove files

by glasswalk3r (Friar)
on Dec 23, 2014 at 19:40 UTC ( [id://1111215]=perlquestion: print w/replies, xml ) Need Help??

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

Greetings monks,

I'm trying to figure out how this onliner to remove files works:

for(<*>){((stat)[9]<(unlink))}

The "*" in the diamond operator is something I can't find any document about it.

Also, calling stat (which will hit $_, filled by the diamond operator of any filename in the current directory) and getting a slice of it (returning mtime of the file as the ninth element of the list) makes no sense to me, specially how the filename information is being given to unlink.

Besides that, calling stat for me makes no sense at all... I could be calling unlink directly, couldn't I? At least it works if I replace everything with an print "$_\n" inside the for loop.

Here is the reference from where I fetched this onliner: http://www.slashroot.in/which-is-the-fastest-method-to-delete-files-in-linux.

Thanks,

Alceu Rodrigues de Freitas Junior
---------------------------------
"You have enemies? Good. That means you've stood up for something, sometime in your life." - Sir Winston Churchill

Replies are listed 'Best First'.
Re: Onliner magic to remove files (useless)
by tye (Sage) on Dec 23, 2014 at 19:57 UTC

    It is equivalent to:

    for( glob("*") ) { stat $_; # Useless code unlink $_; }

    - tye        

      Thanks, Tye. I've been struggling to figure out what the stat() did myself. I was currently exploring that maybe stat threw some sort of error on an unreadable file, directory or something and that would prevent the evaluation of the right hand expression, but all my tests ALWAYS evaluated both sides regardless.

      mr.nick ...

Re: Onliner magic to remove files
by LanX (Saint) on Dec 23, 2014 at 20:07 UTC
    See glob for the meaning of <*>.

    Both unlink and stat operate on $_ which holds the file found by glob.

    The boolean < is mysterious for me, I can only only guess that a warning is triggered in case of error.

    Alternatively the evaluation of this boolean to raise the error got lost while copying.

    Most probably cargo cult.

    Cheers Rolf

    (addicted to the Perl Programming Language and ☆☆☆☆ :)

Re: Onliner magic to remove files
by Anonymous Monk on Dec 24, 2014 at 01:14 UTC
    for(<*>){((stat)[9]<(unlink))}

    The apparently useless stat and < made me a bit curious, so I googled it a bit. There are several places where the above is presented as a one-liner for "fast file deletion", but without explaining what the stat might be for.

    Several people claimed that the Perl solution is faster than find with the -delete option, and I found one (possibly dubious) claim that it's because find uses fstatat64 syscalls while Perl uses lstat64+stat64 syscalls (a quick check on my system appears to confirm this). However, since it isn't my area of expertise, I'm not sure if that causes a speed difference.

    In a post by Kent Fredric - https://www.quora.com/Linux-why-stat+unlink-can-be-faster-than-a-single-unlink - he shows that removing the stat actually gives a minor performance improvement, so I suspect it really isn't necessary.

    My best guess for now is that the code snippet is a bastardization of something like this, and it's just been cargo-culted from there.

Re: Oneliner magic to remove files
by Anonymous Monk on Dec 24, 2014 at 19:09 UTC

    The find based methods in slashroot article are somewhat dubious. Firstly, -exec rm {} \; option will invoke rm for each and every file (also noted by the author). Gnu find offers a nifty feature for such occasions.

    $ time find ./ -type f -exec rm {} \+
    real    0m1.764s
    
    Which builds up argument list, passing that to rm. It's more or less equivalent to the following (except there's no pipe/xargs involved):
    $ time find ./ -type f -print0 | xargs -0 rm
    real    0m1.321s
    

    Using -delete:

    $ time find ./ -type f -delete
    real    0m0.795s
    

    In parallel:

    $ time find ./ -type f -print0 | xargs -0 -P4 -n10000 rm
    real    0m0.571s
    

    Perl versions:

    $ time perl -e 'for(<*>){((stat)[9]<(unlink))}'
    real    0m2.917s
    $ time perl -e 'unlink for <*>'
    real    0m2.308s
    

    Tests were run in a tmpfs backed directory; files created as in the reference article:

    $ for i in $(seq 1 500000); do echo testing >> $i.txt; done
    

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1111215]
Approved by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (8)
As of 2024-04-23 07:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found