LinuxQuestions.org
Latest LQ Deal: Linux Power User Bundle
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 05-10-2011, 11:07 PM   #1
johnychemist
LQ Newbie
 
Registered: Oct 2010
Posts: 10

Rep: Reputation: 0
Auto Unrar files and move whitelist to another directory


Hey guys

I'm really new to scripting in Linux. And have only just managed to puzzle this out, well sort of...

I'm looking for a script that can be run regularly with Cron.

Check a folder for Rar files every few minutes, Unrar if present, and delete the left over files once done.

Be able to specify the directory of which folder to watch within the script.

Run an extension white list (.avi, .mkv, .mp4) and blacklist (rar files) of files to be moved.

Specify within the script which folder to move found files to.

I've seen a few online that does some of this or much more than this but I'm looking for something that just does this in a simple and efficient way... (Also for the life of me, I just can't get how to edit this to do what I'm looking for)

Could someone help out here please?
 
Old 05-11-2011, 01:17 AM   #2
neonsignal
Senior Member
 
Registered: Jan 2005
Location: Melbourne, Australia
Distribution: Debian Jessie (Fluxbox WM)
Posts: 1,387
Blog Entries: 52

Rep: Reputation: 355Reputation: 355Reputation: 355Reputation: 355
This goes through the rar files. For each rar file, it unrars them to an existing temporary directory, removes the rar file, moves the whitelisted files to the media directory, and then cleans up the temporary directory.

Code:
for f in rar_dir/*.rar
do
   unrar e "$f" /tmp/media/
   rm "$f"
   mv /tmp/media/*.{avi,mkv,mp4} media_dir/
   rm /tmp/media/*
done

Last edited by neonsignal; 05-12-2011 at 11:42 PM. Reason: quotes around filenames
 
Old 05-11-2011, 03:00 AM   #3
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,256

Rep: Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686
I personally feel we need a lot more information, if nothing else, what have you tried as you seem to indicate having attempted something?

But my main concern, looking at how I normally receive rar files, is that they are generally pieces of a whole so you would need to know / test
if all pieces have arrived prior to trying to recombine (unrar). Could just be my unfamiliarity with using (un)rar??
 
Old 05-11-2011, 12:06 PM   #4
johnychemist
LQ Newbie
 
Registered: Oct 2010
Posts: 10

Original Poster
Rep: Reputation: 0
Thanks for that script and the quick replies
I ran this as:

#!/bin/bash

for f in /home/mediaserver/UnrarFolder/new/*.rar
do
unrar e $f /home/mediaserver/UnrarFolder/Working/
rm $f
mv /home/mediaserver/UnrarFolder/Working/*.{avi,mkv,mp4,img} /home/mediaserver/UnrarFolder/fin/
rm /home/mediaserver/UnrarFolder/Working/*
done

But I received the following error.

No files to extract
rm: cannot remove `/home/mediaserver/UnrarFolder/new/*.rar': No such file or directory
mv: cannot stat `/home/mediaserver/UnrarFolder/Working/*.avi': No such file or directory
mv: cannot stat `/home/mediaserver/UnrarFolder/Working/*.mkv': No such file or directory
mv: cannot stat `/home/mediaserver/UnrarFolder/Working/*.mp4': No such file or directory
mv: cannot stat `/home/mediaserver/UnrarFolder/Working/*.img': No such file or directory
rm: cannot remove `/home/mediaserver/UnrarFolder/Working/*': No such file or directory

I'm not sure I edited this correctly though.

I have managed to get the script below to work but it doesn't do everything I'm after, maybe I could get some help with editing this to suit?

This script unrar's files, checks the integrity of the file, and cleans up afterwards.
I still would like to:

- Input the directory within the script of where to find the rars
- Input the directory within the script of where to output the completed file and directory (I really need this to move this to another directory)

Also

- If no rars are found, move the directory and file to another directory thats been written into the script.

Could I get some ideas on this?

Also I'm not sure on how I would add this to cron
This command needs to be run from the folder containing the script
./unrarall.sh -d [/this/directory/has/rars] -c

I might be asking for a lot here
Sorry - help appreciated.
---

#!/bin/bash

#unrarall
# Copyright (C) 2011 Brendan Le Foll & Dan Liew
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
##########################################################################

# Set some defaults
declare -x DIR="`pwd`"
declare -ix CLEAN=0
declare -rx UNRARALL_VERSION="0.2"
declare -ix FORCE_CLEAN=0
declare -ix VERBOSE=0
declare -x UNRAR_METHOD="e"

function usage()
{
echo "Usage: unrarall [ --dir DIRECTORY ] [ --clean | --force ] [ --full-path ] [ --verbose ]
unrarall --help
unrarall --version

Usage (short options):
unrarall [ -d DIRECTORY ] [ -c | -f ] [ -v ]
unrarall -h
DESCRIPTON
unrarall is a utility to unrar and cleanup (delete) all rar files within a directory DIRECTORY. Sub-directories are automatically recursed and if a rar file exists in a sub-directory then the rar file is extracted into that subdirectory.

Use --clean if you want to cleanup. Otherwise no cleaning is done. It can also be used to delete rar files that have already been used for extraction with --force. Use with caution!

OPTIONS

-c, --clean Clean after unrar. If the extraction fails then the directory will NOT be cleaned. Use --force to override this.
-d, --dir Use directory DIRECTORY. If this argument is not supplied the current working directory is used.
-f, --force Force clean even if unrar fails. Implies --clean. Use this if you've already used unrarall on the directory before
and now you want to remove the rar files. This should be pretty fast as unrar is set to not overwrite already extracted files.
--full-path Extract full path inside rar files instead of just extracting the files in the rar file which is the default behaviour.
-h, --help Displays this help message and exits.
-v, --verbose Show extraction progress as unrarall executes. This is not done by default
--version Give version information version.

VERSION: $UNRARALL_VERSION

"
}

#function to display pretty messages
function message()
{
#Assume $1 is message type & $2 is message
#See http://www.frexx.de/xterm-256-notes/ for information on xterm colour codes

case "$1" in
error)
#use escape sequence to show red text
echo -e "\033[31m${2}\033[0m" 1>&2
;;
ok)
#use escape sequence to show green text
echo -e "\033[32m${2}\033[0m"
;;
*)
echo "$2"
esac

}

# Parse command line arguments
while [ -n "$1" ]; do
case "$1" in
-h | --help )
usage
exit 0
;;
--version )
echo "$UNRARALL_VERSION"
exit 0
;;
-d | --dir )
shift
DIR="$1"
;;
-c | --clean )
CLEAN=1
;;
-f | --force )
FORCE_CLEAN=1
CLEAN=1
;;
-v | --verbose )
VERBOSE=1
;;
--full-path )
UNRAR_METHOD="x"
;;
*)
# user issued unrecognised option
message error "Unrecognised option: $1"
usage
exit 1
;;
esac
shift
done

# Current Dir check
if [ "${DIR}" == "." ]; then
DIR="`pwd`"
fi

# Check unrar is available
if ! type -P unrar >/dev/null; then
message error "Please install unrar or check your \$PATH"
exit 1;
fi

# Check $DIR exists and is a directory
if [ -d "$DIR" ]; then
echo "Working over directory \"${DIR}\""
else
message error "Cannot find directory \"${DIR}\""
exit 1;
fi

# Check if there is an "unrar" running already, if so, exit
if ps -ef | grep -v grep | grep -v unrarall | grep unrar ; then
message error "unrar is allready running. Please only run this script once"
exit 0
fi

CURRENT_DIR=`pwd`

#find all files
COUNT=0

#modify IFS for new lines so filenames with spaces do not get split
IFS_TEMP=$IFS
IFS=$(echo -en "\n\b")

#assuming only the .rar files are of interest
for file in $(find "$DIR" -name '*.rar'); do
let COUNT=COUNT+1
echo -n "Extracting (${UNRAR_METHOD}) \"$file\"..."
filename=`basename "$file"`
dirname=`dirname "$file"`

#Strip .rar extension off filename
sfilename="${filename%.rar}"

# move to directory
cd "$dirname"

# unrar file with unrar e
if [ "$VERBOSE" -eq 1 ]; then
unrar ${UNRAR_METHOD} -y -o- "$filename"
else
unrar ${UNRAR_METHOD} -y -o- "$filename" >/dev/null
fi
SUCCESS=$?

# if fail remove from count
if [ "$SUCCESS" -eq 0 ]; then
message ok "ok";
else
let COUNT=COUNT-1
message error "failed"
fi

# cleanup all .rar/.r[0-9][0-9]/
if [ "$CLEAN" -eq 1 ] ; then
if [ "$SUCCESS" -eq "0" ] || [ "$FORCE_CLEAN" -eq 1 ]; then
echo "Cleaning $file"
if [ "$VERBOSE" -eq 1 ]; then
rm -v "${sfilename}".rar
rm -v "${sfilename}".r[0-9][0-9]
else
rm "${sfilename}".rar 2>/dev/null
rm "${sfilename}".r[0-9][0-9] 2>/dev/null
fi

else
message error "Couldn't do requested clean because unrar extracted unsuccessfully. Use --force to override this behaviour"
fi
fi
cd "$CURRENT_DIR"
done
IFS=$IFS_TEMP

#If success
if [ "$COUNT" -ne 0 ]; then
EXIT_PHRASE="found and extracted"
if [ "$CLEAN" -eq 1 ]; then
EXIT_PHRASE="found, extracted and removed"
fi
echo "$COUNT rar files $EXIT_PHRASE"
else
message error "no rar files extracted"
fi

Last edited by johnychemist; 05-11-2011 at 07:25 PM. Reason: Update info
 
Old 05-11-2011, 11:19 PM   #5
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,256

Rep: Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686
Well firstly, please use [code][/code] tags around your code to maintain formatting and make it easier to read.

As to the errors you received when executing your edited version of neonsignal's code, the errors mean that the path that you provided
had no rar files in it and so the for loop place the following in $f:
Code:
f="/home/mediaserver/UnrarFolder/new/*.rar"
Quote:
- Input the directory within the script of where to find the rars
- Input the directory within the script of where to output the completed file and directory (I really need this to move this to another directory)
This option does not make so much sense if it is to in fact be an automated job, however, you can pass arguments to
the script and then access them with the following:
Code:
./script.sh dir1 dir2
Then inside script.sh:
Code:
inputDir="$1"
outputDir="$2"
Although on a quick glance I think '-d' covers the first one.
 
Old 05-12-2011, 07:09 PM   #6
johnychemist
LQ Newbie
 
Registered: Oct 2010
Posts: 10

Original Poster
Rep: Reputation: 0
thanks..

apologies for the editing.

I've tried neonsignal's script on another machine, with what I think are your suggestions and hitting the following errors.

Obviously I'm now doing something even more wrong than before.

Quote:
ERROR: Unknown option: rm: cannot remove `/home/goliath/Torrent': No such file or directory
rm: cannot remove `Downloads/2': No such file or directory
rm: cannot remove `-': No such file or directory
rm: cannot remove `Download': No such file or directory
rm: cannot remove `post': No such file or directory
rm: cannot remove `processing': No such file or directory
rm: cannot remove `-': No such file or directory
rm: cannot remove `unrar/Movies': No such file or directory
rm: cannot remove `Post': No such file or directory
rm: cannot remove `Processing': No such file or directory
rm: cannot remove `-': No such file or directory
rm: cannot remove `unrar/*.r01': No such file or directory
mv: cannot stat `/home/goliath/Torrent Downloads/2 - Download post processing - unrar/Movies Post Processing - unrar/*.{avi,mkv,mp4,img,iso}': No such file or directory
rm: cannot remove `/home/goliath/Torrent Downloads/2 - Download post processing - unrar/Movies Post Processing - unrar/*.r*': No such file or directory
----------------------

I've edited the code like this:

----------------------

Quote:
for f in "/home/goliath/Torrent Downloads/2 - Download post processing - unrar/Movies Post Processing - unrar/*.r01"
do
unrar e $f="/home/goliath/Torrent Downloads/2 - Download post processing - unrar/Movies Post Processing - unrar/*.r01"
rm $f
mv "/home/goliath/Torrent Downloads/2 - Download post processing - unrar/Movies Post Processing - unrar/*.{avi,mkv,mp4,img,iso}" "/home/goliath/Torrent Downloads/3 - Download post processing - rename/Movie Post Processing - rename"
rm "/home/goliath/Torrent Downloads/2 - Download post processing - unrar/Movies Post Processing - unrar/*.r*"

done
---------------------

Since I have spaces in my file names, I've included some " ___ " so as to avoid this type of error, its worked elsewhere but here I'm clearly wrong.

I also edited .rar to .r01 as these will normally be multipart rar files but would be good if I could include a few different extensions as triggers to rar the file.

My directories where the rar file will be stored is:
Quote:
/home/goliath/Torrent Downloads/2 - Download post processing - unrar/Movies Post Processing - unrar/
Output directory is:
Quote:
/home/goliath/Torrent Downloads/3 - Download post processing - rename/Movie Post Processing - rename/
Not sure if it will make a difference but the rar / r01 files are stored inside a folder or possibly two folder in the unrar directory

Also no clue as far as how i would construct this in cron.

I'm a newbie
Help very much appreciated
 
Old 05-12-2011, 09:27 PM   #7
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Centos 6.8, Centos 5.10
Posts: 17,241

Rep: Reputation: 2325Reputation: 2325Reputation: 2325Reputation: 2325Reputation: 2325Reputation: 2325Reputation: 2325Reputation: 2325Reputation: 2325Reputation: 2325Reputation: 2325
I don't see any underscores in your version? That would be my first fix.
You can use files/dirs with spaces in them, BUT in *nix by default, params/args to a prog/cmd are separated by whitespace, hence the complications.
Personally I go with the old school *nix guys and never allow spaces in file/dir names, or replace them with underscores before I start.
Makes life much simpler, honest.
 
Old 05-13-2011, 02:21 AM   #8
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,256

Rep: Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686
I am with Chris when it comes to directory / file names not having spaces or other unusual characters that can cause me problems.

Another suggestion might be to change to a while loop being fed by find as this will not suffer the word splitting you get from the for loop:
Code:
while read -r path
do
    <your stuff here>
done< <(find "/home/goliath/Torrent Downloads" -type f -name '*.rar')
Now as long as you use double quotes around the path variable it will maintain form when passed to your commands.
 
Old 05-13-2011, 10:07 AM   #9
johnychemist
LQ Newbie
 
Registered: Oct 2010
Posts: 10

Original Poster
Rep: Reputation: 0
Ok

I have made the changes to the file structure as that sounds like the safest option for other scripts. That leaves me with the following script.

Quote:
for f in /home/goliath/Torrent_Downloads/2_Download_post_processing_unrar/Movies_Post_Processing_unrar/*.r01
do
unrar e $f=/home/goliath/Torrent_Downloads/2_Download_post_processing_unrar/Movies_Post_Processing_unrar/*.{r00,rar}
rm $f
mv /home/goliath/Torrent_Downloads/2_Download_post_processing_unrar/Movies_Post_Processing_unrar/*.{avi,mkv,mp4,img,iso} /home/goliath/Torrent_Downloads/3_Download_post_processing_rename/Movie_Post_Processing_rename
rm /home/goliath/Torrent_Downloads/2_Download_post_processing_unrar/Movies_Post_Processing_unrar/*.r*

done
I'm still getting the following errors though.

Quote:
UNRAR 4.00 beta 3 freeware Copyright (c) 1993-2010 Alexander Roshal

No files to extract
rm: cannot remove `/home/goliath/Torrent_Downloads/2_Download_post_processing_unrar/Movies_Post_Processing_unrar/*.r01': No such file or directory
mv: cannot stat `/home/goliath/Torrent_Downloads/2_Download_post_processing_unrar/Movies_Post_Processing_unrar*.avi': No such file or directory
mv: cannot stat `/home/goliath/Torrent_Downloads/2_Download_post_processing_unrar/Movies_Post_Processing_unrar*.mkv': No such file or directory
mv: cannot stat `/home/goliath/Torrent_Downloads/2_Download_post_processing_unrar/Movies_Post_Processing_unrar*.mp4': No such file or directory
mv: cannot stat `/home/goliath/Torrent_Downloads/2_Download_post_processing_unrar/Movies_Post_Processing_unrar*.img': No such file or directory
mv: cannot stat `/home/goliath/Torrent_Downloads/2_Download_post_processing_unrar/Movies_Post_Processing_unrar*.iso': No such file or directory
rm: cannot remove `/home/goliath/Torrent_Downloads/2_Download_post_processing_unrar/Movies_Post_Processing_unrar/*.r*': No such file or directory
Could this be because the rar, r00 files are in a subdirectory in the directories?
I have rechecked the directories by dragging and dropping folders into terminal so they are correct.

Any ideas?
 
Old 05-13-2011, 10:21 AM   #10
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,256

Rep: Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686
Quote:
unrar e $f=/home/goliath/Torrent_Downloads/2_Download_post_processing_unrar/Movies_Post_Processing_unrar/*.{r00,rar}
This line cannot work as you are trying to assign something to $f ... or is this maybe a typo?
 
Old 05-13-2011, 11:21 AM   #11
johnychemist
LQ Newbie
 
Registered: Oct 2010
Posts: 10

Original Poster
Rep: Reputation: 0
Thats whats in neonsignals script:

Quote:
for f in rar_dir/*.rar
do
unrar e "$f" /tmp/media/
rm "$f"
mv /tmp/media/*.{avi,mkv,mp4} media_dir/
rm /tmp/media/*
done
Am I interpreting this script correctly?
This what I have now.
I'm at a loss here with this

Quote:
for f in /home/goliath/Torrent_Downloads/2_Download_post_processing_unrar/Movies_Post_Processing_unrar/*.r01
do
unrar e "$f" /home/goliath/Torrent_Downloads/2_Download_post_processing_unrar/Movies_Post_Processing_unrar/*.{r00,rar,r01}
rm "$f"
mv /home/goliath/Torrent_Downloads/2_Download_post_processing_unrar/Movies_Post_Processing_unrar/*.{avi,mkv,mp4,img,iso} /home/goliath/Torrent_Downloads/3_Download_post_processing_rename/Movie_Post_Processing_rename/
rm /home/goliath/Torrent_Downloads/2_Download_post_processing_unrar/Movies_Post_Processing_unrar/*.r*

done

Last edited by johnychemist; 05-13-2011 at 12:57 PM.
 
Old 05-13-2011, 01:08 PM   #12
johnychemist
LQ Newbie
 
Registered: Oct 2010
Posts: 10

Original Poster
Rep: Reputation: 0
Update: This script is not even finding rar, r00 files to extract
has this script got any potential or am I wasting my time with this.

I need a script that will

Unrar a folder location
and move the whitelist extension to another directroy
clean up after itself

It can't be this freaking difficult could it?

No half answers either plse
 
Old 05-14-2011, 12:18 AM   #13
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,256

Rep: Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686
Well you have removed the equals (=) sign that was previously on the line I indicated, but your unrar line is not the same as neonsignal's as he has a directory as
the third argument to unrar whereas you have what looks to be file listing:
Code:
unrar e "$f" /tmp/media/

unrar e "$f" /home/goliath/Torrent_Downloads/2_Download_post_processing_unrar/Movies_Post_Processing_unrar/*.{r00,rar,r01}
You can see these are clearly not the same. It will also be why the mv and last rm lines do not work as nothing has been created (probably would help to have a test in
there to see if they are there before moving or removing).

Also, are ALL of your rar files ending in .r01? Because these are the only things being passed into $f. When I personally unrar stuff (admittedly through manual process and using
Nautilus) I select the .rar file most of the time.

Maybe you need to go back and look at your manual process and then reproduce that in the script?
 
Old 05-14-2011, 05:38 AM   #14
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,256

Rep: Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686Reputation: 2686
Ok ... so you got me to thinking and I have started to play with this idea on my own machine (the extraction at least, I will leave the cron to one of the professionals).
Now from what I can see the only real diff may be that I prefer and use 7z as opposed to (un)rar but the premise should be the same.
See if this helps:
Code:
#!/bin/bash

DEFAULT=/home/goliath/Torrent_Downloads/
INPUT="${DEFAULT}2_Download_post_processing_unrar/Movies_Post_Processing_unrar/"
OUTPUT="${DEFAULT}3_Download_post_processing_rename/Movie_Post_Processing_rename/"

while read -r DIR
do
    if cfv -q -p "$DIR"
    then
        if 7z e "$DIR/*.rar" -o "$OUTPUT"
        then
            FILE[++CREATED]="$(7z l $DIR/*.rar | awk 'NR == 4{print $NF}' RS="[- ]+\n")"
        fi
    fi
done< <(find "$INPUT" -type f -name '*.sfv' -printf "%h\n")

(( CREATED )) && echo "$CREATED file(s) were created.  Name(s) are ${FILE[*]}"

exit 0
I have tried to change it to your structure as best as possible, but it should help you with what you want to do.

Differences:

7z in place of unrar

cfv used to check that the pieces of rar files are all accounted for (obviously not required if all your rars are single files although it could also check that all of your file has arrived)

Last edited by grail; 05-14-2011 at 05:40 AM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
move files of a particular directory visitnag Linux - Desktop 17 09-27-2008 10:24 PM
move files of a particular directory visitnag Programming 2 08-25-2008 10:45 PM
move files of a particular directory visitnag Programming 1 08-24-2008 03:02 PM
Move directory of files siva19185 Linux - Newbie 3 07-02-2008 03:59 AM


All times are GMT -5. The time now is 01:01 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration