New at this. I need to use a postinstall script to move a file and a folder to the user's Application Support folder on a Mac. For the file I only want to move it if the file doesn't already exist. I do not want to overwrite it if if does exist. Here is my script. It runs but nothing gets copied. I'm using the Packages app, btw, and this script is loaded into the postinstall script tab.
#!/bin/sh
if ! "/Library/Application Support/MyApp/MyApp user dict"; then
mv "$1/Contents/Resources/MyApp user dict" "/Library/Application Support/MyApp/.";
fi
mv "$1/Contents/Resources/Spellcheck Dictionary" "/Library/Application Support/MyApp/.";
exit 0
User-specific tasks generally do not belong in installer scripts -- remember that there may be multiple users on a machine, and that some of them may not be accessible when your installer is running. (For example, users may have encrypted home directories, or may not exist until after your installer is run.) If your application needs to copy files to the user's home directory, it should probably do this when it is first launched.
Nevertheless, I see several specific issues with this script:
Your script refers to $1 in several places. Are you sure that your script has an argument passed to it on the command line?
The correct syntax to test if a file does not exist is:
if [ ! -f "/path/to/file" ] ; then …
Your script is missing the square brackets and -f condition. (For details, see man test.)
Assuming that $1 is supposed to be the path to the current user's home directory, you have the arguments to mv backwards. The destination comes last, not first. (The syntax is essentially mv from to.)
Related
I have folder "destination/" and inside the destination folder, it contains executable grade1. My current directory is "destination/"
I'm Trying to run
for i in FILES/*; do ./grade1 $i done
Which it keep says
./grade1 no such file or directory
Weird part is that, when I just copy the code to command line and run it, it works fine. Problem only arises when I do it in shell script
I don't think that grade1 really is in your current working directory, as you claim. I suggest that you verify this also check the permissions of your executable. Extend your code to
echo current directory is $PWD
ls -l grade1
for i in FILES/*; do ./grade1 $i done
This should reveal the source of your problem.
One simple way to fix this problem might be to start using FULL path of grade1 executable file
for i in FILES/*; do {FULL_PATH}/grade1 $i done
I have some software that exports a file called My Library.bib to a folder called thesis. Assume that the name of the exported file is fixed. Every time I export such a file, I want to:
Delete any old files called MyLibrary.bib if they exist.
Remove the space from this new file so that it becomes the up-to-date MyLibrary.bib.
I've tried making an Automator 'folder action' as follows:
... However, while the shell script works perfectly if run manually, the folder action itself never appears to trigger.
Folder actions are nonetheless enabled (see below settings), and other folder actions do seem to work.
Summarily, I just want any files named My Library.bib entering the thesis folder (at any time, automatically) to become renamed to MyLibrary.bib, replacing any existing MyLibrary.bib files. Any ideas what's going wrong, or how else to achieve this? Thanks in advance.
When you use the "Run Shell Script" action, the current directory is the Home folder, not the "thesis" folder.
So, you must use the cd command to change the current directory
Informations:
The "Get Folder Content" action is useless for what you want to do,
you can remove it.
The rm command is not necessary, you can use the mv -f to
overwrite an existing file
read firstLine ### get the path of the first dropped item
myDir=$(dirname "$firstLine") ### get the parent (this folder action)
cd "$myDir" && if [ -f "My Library.bib" ]; then
mv -f "My Library.bib" "MyLibrary.bib"
fi
I created this simple script to allow the user to remove files created by the web server in his home directory without giving him "su". Both scripts are set with "chmod 4750".
The craziest thing is that they DID work and now they don't. Here's the scripts:
#!/bin/bash
# Ask for directory to delete
echo "Enter the file or directory you would like to delete, the assumed path is /home/user"
read DIRECTORY
rm -rf /home/user/"$DIRECTORY"
echo "Deleting /home/user/$DIRECTORY ..."
exit 0
2:
#!/bin/bash
# Reset permissions
echo "Resetting the ownership of the contents of /home/user to user."
chown -R user /home/user
exit 0
I will make them a little more advanced and work for multiple users but right now I cannot even get the simple version to work. It works when run as root of course. It used to work when run as user 'user' but now it doesn't. I get this:
user#dev:/home/user$ delete.sh
Enter the file or directory you would like to delete, the assumed path is /home/user/[your input]
test-dir
rm: cannot remove ‘/home/user/test-dir/test-file’: Permission denied
Deleting /home/user/test-dir ...
and
chown: changing ownership of ‘/home/user/test-dir’: Operation not permitted
What can possibly be the problem?
-rwsr-x--- 1 root user 291 Nov 6 05:23 delete.sh
-rwsr-x--- 1 root user 177 Nov 6 05:45 perms.sh
There is a pretty comprehansive answer at https://unix.stackexchange.com/questions/364/allow-setuid-on-shell-scripts
Bottom line is that there are two main points against it:
A race condition between when the Kernel opens the file to find which interpreter it should execute and when the interpreter opens the file to read the script.
Shell scripts which execute many external programs without proper checks can be fooled into executing the wrong program (e.g. using malicious PATH), or expand variables in a broken way (e.g. having white space in variable values), and generally it has less control on how well the external programs it executes handle the input.
Historically, there was a famous bug in the original Bourne shell (at least on 4.2BSD, which is where I saw this in action) which allowed anyone to get interactive root shell by creating a symlink called -i to a suid shell script. That's possibly the original trigger for this being prohibited.
EDIT: To answer "How do I fix it" - configure sudo to allow users to execute only these scripts as user root, and perhaps use a trick like in https://stackoverflow.com/a/4598126/164137 to find the original user's name and force operation on their own home directory, instead of letting them pass in any arbitrary input (i.e. in their current state, nothing in the scripts you include in your question prevents user1 from executing the scripts and passing them users2's directory, or any directory for that matter)
On OS X, I'm writing a bash script to be run as a user, not root. Every so often I need to escalate to root to run certain commands.
In one section I'm trying to iterate over the contents of a directory owned by root with the permissions drwx------, which means I can't glob the contents of the directory as a normal user.
This doesn't work:
sudo for files in "/System/Library/User Template"/*
do
some command "$files"
done
What I would like to do is this:
for files in "/System/Library/User Template"/*
do
sudo some command "$files"
done
This is a new system bootstrap script, so I'd like to keep everything in one script and I definitely cannot run the whole thing as root. I'm wondering:
If there's a proper way to escalate to glob a directory in a for loop.
If I should change the permissions as root, run the code, change the permissions back.
I think you can only consider calling another script that's meant to run as root instead and use sudo with it.
Although maybe you can run bash reading commands from input:
sudo bash -s <<'EOD'
for files in "/System/Library/User Template"/*; do
some command "$files"
done
EOD
I am new to unix and am practicing a simple script to unzip a load of files within a specified directory. I need the program to move the zipped file into another folder when it is done unzipping it (I called this oldzipped folder). For simplicity, I have removed the part of the code unzipping the file and currently have the program working for a specific file rather than the *tar.7z file extention. For some reason, the mv statement is not working. Unix is saying the following when I try to run the script. Could someone give me a hand with this? Again, I know this is the long way of doing things, but I want practice writing a script. Please be nice, as I am very new to Unix :(
unzip5: line 14: [ASDE0002.tar.7z]: command not found
#!~/bin/bash
# My program to try to unzip several files with ending of tar.7z
# I have inserted the ability to enter the directory where you want this to be done
echo "What file location is required for unzipping?"
read dirloc
cd $dirloc
mkdir oldzippedfiles
for directory in $dirloc
do
if
[ASDE0002.tar.7z]
then
mv -f ASDE0002.tar.7z $dirloc/oldzippedfiles
fi
done
echo "unzipping of file is complete"
exit 0
[ is the name of a (sometimes built-in) command which accepts arguments. As such you need to put a space after it as you would when invoking any other program. Also, you need a test. For example, to determine if the file exists and is a file, you need to use -f:
if [ -f ASDE0002.tar.7z ]
then
mv -f ASDE0002.tar.7z $dirloc/oldzippedfiles
fi
Here are some other possible tests.