How do I make this if then else script - macos

I've been trying to make this if then else script but its wrong every time.
I am brand new at this, maybe I have taken more than I can chew but I am trying to make a script that runs at launch that does this
If file exists /Users/Bob/Library/Safari/Bookmarks.plist
then do nothing
if file does not exist ( i assume this is "else") then move file from /Library/Application\ Support/Bookmarks.plist to /Users/Bob/Library/Safari/Bookmarks.plist
Any feedback is greatly appreciated, thanks in advance.

What you described could be written like that in pseudo code:
if file_exists("/Users/Bob/Library/Safari/Bookmarks.plist")
exit
if not file_exists("/Users/Bob/Library/Safari/Bookmarks.plist")
move("/Library/Application\ Support/Bookmarks.plist", "/Users/Bob/Library/Safari/Bookmarks.plist")
As you can see, the first "branch" is not really used, as you anyway plan to ignore this case.
But if we assume, that in the first case, you actually want to do something, like print a nice message, you could write it like that:
if file_exists("/Users/Bob/Library/Safari/Bookmarks.plist")
print("Nothing to do!")
else
move("/Library/Application\ Support/Bookmarks.plist", "/Users/Bob/Library/Safari/Bookmarks.plist")
As you can see, in the this example, the "else" part is equivalent to saying "if not file_exists(...)". You could also reverse the order by using "not":
if not file_exists("/Users/Bob/Library/Safari/Bookmarks.plist")
move("/Library/Application\ Support/Bookmarks.plist", "/Users/Bob/Library/Safari/Bookmarks.plist")
else
print("Nothing to do!")

DST="/Users/Bob/Library/Safari/Bookmarks.plist"
SRC="/Library/Application\ Support/Bookmarks.plist"
if [ ! -f "$DST" ]; then
mv "$SRC" "$DST"
fi
This will see if the destination exists. If not, it will move the file. Realistically there should be additional error checking, and I'm not certain a move is the best approach, since there would no longer be an "original" file.

Related

Detecting that files are being copied in a folder

I am running a script which copies one folder from a specific location if it does not exist( or is not consistent). The problems appears when I run concurently the script 2+ times. As the first script is trying to copy the files, the second comes and tryes the same thing resulting in a mess. How could I avoid this situation? Something like system wide mutex.
I tryed a simple test with -w, I manually copied the folder and while the folder was copying I run the script:
use strict;
use warnings;
my $filename = 'd:\\folder_to_copy';
if (-w $filename) {
print "i can write to the file\n";
} else {
print "yikes, i can't write to the file!\n";
}
Of course this won't work, cuz I still have write acces to that folder.
Any ideea of how could I check if the folder is being copied in Perl or usingbatch commands?
Sounds like a job for a lock file. There are myriads of CPAN modules that implement lock files, but most of them don't work on Windows. Here are a few that seem to support Windows according to CPAN Testers:
File::Lockfile
File::TinyLock
File::Flock::Tiny
After having a quick view at the source code, the only module I can recommend is File::Flock::Tiny. The others seem racy.
If you need a systemwide mutex, then one "trick" is to (ab)use a directory. The command mkdir is usually atomic and either works or doesn't (if the directory already exists).
Change your script as follows:
my $mutex_dir = '/tmp/my-mutex-dir';
if ( mkdir $mutex_dir ) {
# run your copy-code here
# when finished:
rmdir $mutex_dir;
} else {
print "another instance is already running.\n";
}
The only thing you need to make sure is that you're allowed to create a directory in /tmp (or wherever).
Note that I intentionally do NOT firstly test for the existence of $mutex_dir because between the if (not -d $mutex_dir) and the mkdir someone else could create the directory and the mkdir would fail anyway. So simply call mkdir. If it worked then you can do your stuff. Don't forget to remove the $mutex_dir after you're done.
That's also the downside of this approach: If your copy-code crashes and the script prematurely dies then the directory isn't deleted. Presumably the lock file mechanism suggested in nwellnhof's answer behaves better in that case and automatically unlocks the file.
As the first script is trying to copy the files, the second comes and
tries the same thing resulting in a mess
A simplest approach would be to create a file which will contain 1 if another instance of script is running. Then you can add a conditional based on that.
{local $/; open my $fh, "<", 'flag' or die $!; $data = <$fh>};
die "another instance of script is running" if $data == 1;
Another approach would be to set an environment variable within the script and check it in BEGIN block.
You can use Windows-Mutex or Windows-Semaphore Objects of the package
http://search.cpan.org/~cjm/Win32-IPC-1.11/
use Win32::Mutex;
use Digest::MD5 qw (md5_hex);
my $mutex = Win32::Mutex->new(0, md5_hex $filename);
if ($mutex) {
do_your_job();
$mutex->release
} else {
#fail...
}

Why won't cat work inside my bash-script?

I want to be able to display the content of my command-list document but whenever I do it just prints out "./commands.txt" but if I try the same thing outside of my script it works just fine.
This is my code:
helpFile="./commands.txt"
if [ "$com" = "help" ]
then
cat $helpFile
fi
I don't see where you get the $com variable from, but if you set it based on the first argument this should work:
#!/bin/bash
helpFile="./commands.txt"
com=$1
if [ "$com" = "help" ]
then
cat $helpFile
fi
In the above example $com will be set to the first argument passed to the script, so if you would like to display the contents of ./commands.txt you would call it like ./<script.sh> help
I'm also thinking that you should check so the file really does exists in the current working directory or perhaps try to use an absolute path i.e:
helpFile="/home/commands.txt"
I found out what was wrong. My text editor screwed up and was saving all the new edited content on the desktop instead of the folder with the script and text file. Anyways, thanks for all your help guys, I really appreciate it :)

bash script, prompt user to select ID or name completion

I am working on a script that reads the directories in a path and prompts the user for witch directory to choose. The script so far looks like this:
select choises in ${list_files[#]}; do
if CONTAINS_ELEMENT $choises "${list_files[#]}"; then
break
else
echo "invalid choise (PS use the ID numbers)! Try again:"
fi
done
the "CONTAINS_ELEMENT" thingy is a function that checks if the variable $choises is a member of the list_files array. This script works fine, and the output is something like this:
1) first_folder
2) second_folder
3) yet_another_folder
And the user can choose witch folder by typing in the corresponding ID value (ie "2" for "second_folder").
What I am struggling with is this: Is there a way to check if the supplied answer is a correct number -or- a correct file name? And if you can write in the file name manually, is there a way to implement name completion in this script?
The actual reply to select is held in the variable $REPLY, I need to somehow check both $choises and $REPLY. The completion mechanism is much more tricky I suspect..
Does anyone have a good suggestion here? It would be very cool if you could help me get in these features!!
select choises in ${list_files[#]}; do
if CONTAINS_ELEMENT $choises "${list_files[#]}" || CONTAINS_ELEMENT $REPLY "${list_files[#]}"; then
break
else
echo "invalid choise (PS use the ID numbers)! Try again:"
fi
done
This makes both the ID number and the full directory name work, the code is a bit ugly though, and there is no name completion.

How to wget a file at a moving adress?

I am trying to download a PDF file from a website, I know the name of the file, e.g. foo.pdf, but It's location changes every few weeks:
e.g.
www.server.com/media/123456/foo.pdf
changes into
www.server.com/media/245415/foo.pdf
The number is always a six-figure number, so I tried using a bash script to go through all 10 million of them, but that obviously takes a lot of time:
i=0
until [ "$RC" == "0" ] || [ $i == 1000000 ]
do
b=$(printf %06d $i)
wget -q http://www.server.com/media/${b}/foo.pdf -O bar.pdf
export RC=$?
i=$(($i + 1))
done
For wrong addresses I just get 404 errors.
I tested it around the currently correct address and it works.
Does anyone know a faster way to solve this problem?
If that page is linked form anywhere else, then you can get the link from there, and just get the file. If it's not, you are probably out of luck.
Note that most servers would consider trying to hit the webserver 1,000,000 times abuse, and would ban your IP for even trying.
Follow the values from time to time and work out if they're algorithmic or not. As zigdon said above though, if you have the source for the link, just wget that first, and follow the link to the PDF.

What does this bash script function does

I am new to shell scripting and i found this function in a given script file.
##############################
# rotate_daily(filename)
rotate_daily() {
_code=0
_file_src=$1
_today=`date '+%Y-%m-%d'`
_file_dest=${_file_src}.${_today}
if [ -f ${_file_dest} ]; then
printk "rotate_daily(): ${_file_dest} already exist"
_code=1
else
if [ -f ${_file_src} ]; then
printk "rotate_daily(): ${_file_src} => ${_file_dest}"
cp -p ${_file_src} ${_file_dest}
_code=$?
>${_file_src}
fi
fi
}
I understand this is kind of coping file from one location to another location. But, it is not rotating right?. could somebody explain me what it is really does.
thanks in advance for any help
It copies _file_src to the location file_dest unless _file_dest already exists. An informative message will be printed that tells you if the file already exists or file_src_ will be copied, It also moves _file_src only if it is a file.
EDIT: forgot to mention what the command >{_file_src} does - it simply wipes out the contents of the source file. So you will have the contents of _file_src moved to file_dest in the end and _file_src will be empty. I can't figure why not simply do a move(with mv) and then create an empty file, but that's your question.
If the time stamped file already exists, this code snippet does nothing but print a message via printk indicating that. If it does not exist, it copies the source file to it and truncates the source file. I would guess that the line you are not quite understanding is:
>${_file_src}
That line truncates the original file after it has been copied. Note that there is a race condition, and any data written to the file between the copy and the truncation will be lost.

Resources