A script, perhaps? - GNU/Linux

Users browsing this thread: 8 Guest(s)
Gen
Long time nixers
Hey all,

I'm curious, as to anyone who knows of a script or something simular that can do this one simple thing:

Move every item that gets placed on my desktop, to my ~/Documents folder. I'm running OS X.

Basically, instead of changing and configuring twenty applications and features I didn't even know exist that automatically place shit in ~/Desktop, I want them to all place them in ~/Documents.

But with ease (Script).
venam
Administrators
I won't post a script but I can clear your mind about the process of writing it.
You have two options. Or you use a notifier, that will buzz the program when the directory changes, or you can run a daemon that will stay in the background and check the Desktop every x-minutes, which can be resource hungry (polling).
I'm not sure if there's a notify library on OSX, on Linux there is the inotify API implemented in the kernel. Also, the notification of changes system might already be implemented in the language you will use to write the script.
Then the rest should just be about checking if there's content on the desktop and moving it to the other directory.
yrmt
Grey Hair Nixers
You can use a file watcher that moves to the place you want like this: https://github.com/howeyc/fsnotify
dami0
Long time nixers
mv ~/Desktop/* ~/Documents/ in a crontab.

Uber milk.
pvtmert
Members
there is command in linux called inorifywait, you can use like:
inotifywait -emoved_to -emodify -ecreate -c desk/
and gives output in csv format: -c flag
desk/,CREATE,a
desk/,MODIFY,a
(a is a file name)
while true; do inotifywait -emoved_to -emodify -ecreate -cdesk/ | cut -d, -f3 | mv $(cat -) ~/doc; done
will do your job
springworm
Registered
I know I'm late, but the cleanest option would probably be to set up a folder action with applescript.

https://developer.apple.com/library/mac/...tions.html
sodaphish
Long time nixers
inotify is a good approach; I've used FAM for similar purposes on Linux, but it is quite processor intensive. That said, I have some FAM code that would work for what you're trying to do.

Code:
#!/usr/bin/perl
# slattrs.pl v0.1.0 by C.J. Steele, CISSP, <coreyjsteele@yahoo.com>
#
# This program monitors directories (via FAM) and sets attribute bits on files
# created in those directories so the files are append-only.  This is used,
# almost exclusively, to secure log servers so that the logs are append-only
# and cannot be edited by rouge users, hackers, or unscrupulus sysadmins (who
# might be covering their butts on something dumb they did.)
#
# You can configure which directories are monitored by mangling the
# %monitor_these hash, which is in the format of "'directory' => 'flag'" where
# "directory" is the full path you want to monitor and "flag" is either "r" or
# "n", meaning recursive or not.  Subdirectories of recursively monitored
# directories will be monitored as opposed to non-recursive directories which
# will NOT monitor subdirectories.  You can also specify which files you do NOT
# want to be included in the monitoring (there are some files which need to be
# excluded, such as your Xorg.0.log files) or functionality is broken.
#
# You can also tune where the pidfile is dropped to suit local environments.
#
# For `slattrs.pl` to run, You'll have to have FAM (and thus portmapper)
# running on the machine to be monitored.  These need to be setup with due care
# to ensure they can not be accessed from beyond the local machine.
#
# TODO:
# * catch sigint so we can die-out properly and kill off our pidfile and
#     cleanup other things.
#
use strict;
use SGI::FAM;
use Filesys::Ext2 qw( lsattr chattr );
use Shell qw( find );
use English;

my %monitor_these = (
    "/var/log/hosts" => "r",
    "/var/log" => "n"
    );    
my @exceptions = ( "/var/log/Xorg.0.log", "/var/log/Xorg.0.log.old" );
my $pidfile = "/tmp/slattrs.pid";




########################################################################
#        DO NOT EDIT ANYTHING BELOW THIS POINT UNLESS YOU REALLY       #
#                KNOW WHAT YOU'RE DOING AND ACTUALLY DO                #
########################################################################


# my debug symbols will not be particularly useful to discern additional
# functionality, so don't enable this unless you're making changes and you want
# to follow my debug convention.
my $DEBUG = 0;


# we have to be root to use this... if you stopped using Filesys::Ext2, and did
# system calls to `chattr`, you could setuid the binaries and get rid of
# needing root, but that'd be an epically crappy idea, so don't.
if( $UID != 0 )
{
    print "E: you must be root!\n";
    exit( 1 );
}

# check to see if other instances of this script are running and die if they
# are.
justme();

# sorta demonizing... I you still need to `nohup` the process or it dies with
# your tty.  This is all handled through the slattrs.init script, for simplicity
fork && exit;

print "...dropping to the background. (pid $$)\n";

open( PIDFILE, ">$pidfile" ) or die( "E: couldn't open $pidfile" );
print "D: writing pidfile\n" if( $DEBUG );
print PIDFILE "$$\n";
close( PIDFILE );


#
# load up the directories we want to monitor -- these can be recursive or not.
# See the bits of documentation up by %monitor_these for more
my $fam=new SGI::FAM;
foreach my $dir ( keys %monitor_these )
{
    if( -r $dir and -d $dir )
    {
        # its a directory and its readable...
        if( $monitor_these{$dir} =~ /^r/i )
        {
            #this is a recursive directory, load its subdirectories
            foreach my $sd ( find( "/var/log/hosts", "-type d", "-print" ) )
            {
                chomp( $sd );
                if( -r $sd and -d $sd )
                {
                    $fam->monitor( "$sd" );
                    print "D: FAM monitor setup on '$sd'\n" if( $DEBUG );
                } else {
                    # not sure how we'd ever get here given we need to run as root
                    # and the other checks that occur, but better safe than sorry.
                    print "E: cannot read $dir or it is not a directory\n";
                } #end if
            } #end foreach
        } else {
            # not a recursive loading directory, ignore sub directories.
            $fam->monitor( $dir );
        }
    } else {
        print "E: cannot read $dir or it is not a directory\n";
    } #endif
} #end foreach


#
# This is where we do the actual monitoring... the only bit thats slightly
# confusing, frankly, is the $fam->which( $fe) bit that produces the
# non-terminated directory name the event occurred in.
while( 1 )
{
    # this should be a little less blocking... not that it matters particularly.
    if( $fam->pending )
    {
        my $fe = $fam->next_event;
        if( $fe->type eq "create" )
        {
            my $file = $fam->which( $fe ) . "/" . $fe->filename;
            if( -f $file and ! isin( $file, @exceptions ) )
            {
                # we only want to be trying to chattr /files/ that are created
                print "D: file=$file\n" if( $DEBUG );
                print "D: 'create' event detected on $file\n" if( $DEBUG );
                eval {
                    print "D: lsattr before ", lsattr( ($file) ), "\n" if( $DEBUG );
                    chattr( "+a", ($file) );
                    print "D: lsattr after ", lsattr( ($file) ), "\n" if( $DEBUG );
                }; if( $@ ){
                    print STDERR "E: couldn't chattr() ", $fe->filename, " ($@)\n";
                } #end if
            } #end if
        } #end if
    } else {
        #this may need to be tuned
        sleep 1;
    } #endif
} #    end while

    
exit( 0 );




sub justme
# checks to see if our pidfile exists (is open()-able) and if so, gets the pid
# and kills it with signal zero to see if its there, if it isn't, we return
# (and thus we continue processing.)
{
    if( open( PIDFILE, $pidfile ) )
    {
        my $pid; chop( $pid = <PIDFILE> );
        kill( 0, $pid ) and die "$0 already running (pid $pid).";
    }
} #end justme()




sub isin
# checks an array (@a) for the occurence of a specific element ($e) and returns
# a 1 (true) or 0 (false)
{
    my( $e, @a ) = @_;
    foreach( @a )
    {
        return 1 if( $_ eq $e );
    }
    return 0;
} #end isin()

I should stress that instead of using chattr(), you would call something equiv to `mv`. I haven't done any of the research to see what the appropriate call would be in perl, but the example stands as a solid piece of production code I used on a logging server to make sure all files in a directory were append only. you can leverage the same event engine to ensure your desired behavior is followed.
z3bra
Grey Hair Nixers
inotify is linux-specific, and seeing his (or her) avatar, we're probably searching a solution for Mac
BANGARANG, MOTHERFUCKER
sodaphish
Long time nixers
(04-07-2014, 02:52 AM)z3bra Wrote: inotify is linux-specific, and seeing his (or her) avatar, we're probably searching a solution for Mac

my solution relies on FAM (from SGI) -- you can get FAM on a variety of platforms, including *BSD, which makes me think it should be portable to OSX. Also, since his needs don't include changing attributes on files, you could strip-out `use Filesys::Ext2...`, and include whatever appropriate module would provide the useful bits for your application.

Just thinking out loud here.

Cheers,
Soda
venam
Administrators
I just noticed that this is posted in the GNU/Linux section and not in the OSX section.
dami0
Long time nixers
Or you could symlink ~/Documents/ to ~/Desktop/ and not display icons. Even more milk.