Shell Command For File To Delete Itself - macos

I want to make a file that runs a script, then deletes itself. I know that its root would most likely be "~/Library/Downloads/filename.app". How would I go about having it self destruct? I'm working in script editor.

I'm not sure if I understand correctly as shell script would traditionally have .sh suffix instead of .app one (if any) and I'm not familiar with anything that I'd call "script editor", but alas here's my solution.
If you are in bash environment, you can make use of the BASH_SOURCE array. Provided that you didn't change the current working directory, you can directly call
rm "${BASH_SOURCE[0]}"
(or just rm "$BASH_SOURCE").
If you are using cd or make larger script, it might be advisable to save fully resolved path to the script at the beginning and remove that file at the end (not somewhere in the middle as running bash scripts are NOT independent on their source files*) like so:
#!/bin/bash
self=$(realpath "${BASH_SOURCE[0]}")
#
# code so ugly I want to delete it when I'm done
#
rm "$self"
*Edit shell script while it's running

Related

How to make a bash command executable from any directory in Windows?

I have made a few bash scripts that I have saved to individual folders. I have Windows 10. The scripts have functions that executes commands in bash. I am now able to execute these .sh scripts from any directory, since I have added the folders they are saved in to the path variable. But I want to make it even easier for me, and be able to only have to type the function in the bash console to execute the command.
This is an example of one of the scripts. It is saved as file_lister.sh. I am able to run this by typing "file_lister.sh" but I want to run it by only typing the function name in the script, which is "list_files". How do I do this? Thanks in advance.
#!/bin/bash
function list_files(){
cp C:/Users/jmell/OneDrive/projects/file_lister/file_lister.py file_lister.py
python file_lister.py
cwd=$(pwd)
if [ $cwd != "/c/Users/jmell/OneDrive/projects/file_lister" ]
then
rm file_lister.py
fi
}
list_files
Unless you source all of your scripts (e.g. in your .bashrc file), the functions won't be defined. However, your function is doing a lot of extra work that it really shouldn't be. The example script can be reduced to
#!/bin/bash
python C:/Users/jmell/OneDrive/projects/file_lister/file_lister.py
Better, yet, keep in mind that the shebang line is read and stripped off by the shell. It specifies the interpreter to use. Instead of creating a wrapper script, add the following line to file_lister.py:
#!/path/to/python
At that point, I'd also recommend renaming file_lister.py to just file_lister.

Why can't my shell function change directory from piped input?

I have made a cli which computes the location of a certain directory, and I would really like to have the script change into it. My first approach was ./myscript | cd which I've learned doesn't work as 1. cd doesn't take piped arguments, and 2. the script won't be allowed to change the directory of the parent shell.
I learned that there are workarounds, and I tried creating a function in .bash_profile:
function cdir(){
DIR=""
while read LINE; do
DIR=$LINE
done
echo $DIR
cd $DIR
}
Now running ./myscript | cdir the correct directory is output, however, the directory is still not changed.
Using command substitution works: cd $(./myscript), but I'd really prefer to be able to write this using pipe. Do you have any idea how I can get this to work, or at least explain why it isn't possible?
cd changes the current working directory, which is an attribute of the process. When you use a pipeline, shell creates a subprocess and the effect of cd (inside your function) is lost when the subprocess finishes.
cd -- "$(./myscript)"
is the right way of doing it. Here, cd runs in your current shell.
See also:
Why doesn't "cd" work in a bash shell script?
chdir() doesn't change directory after exiting to shell on Unix & Linux Stack Exchange

Parent directory of a script

So I am a rookie in Linux and I need some help. I have to write a bash script in which I have to use the parent directory of the script to create a file there, wherever the script would be. It should look like this:
If my script it's in "/home/student/", I need to create, using an in-script command another file called txt in /home/. Any ideas please? Thank you.
There's a subtlety if you want to be able to run your script from anywhere.
eg: if your script is in /home/myHome/someDir/someOther, and you want to create a file in /home/myHome/someDir wherever you are when you run your script.
To solve it, you just need to first derive the directory where your script is.
It can be done using:
SCRIPT_DIRECTORY="$(dirname "$0")"
touch "$SCRIPT_DIRECTORY/../myFile.txt"
Edit: Actually it can be even more subtle, if you want to handle symlinks. ie: if the symlink /home/myHome/mySymlink points at your script, and is the one actually being called, then the previous script will consider /home/myHome/ instead of /home/myHome/someDir/someOther
To handle this case you can do
if [ -L "$0" ] && [ -x $(which readlink) ]; then
ACTUAL_SCRIPT_FILE="$(readlink -mn "$0")"
else
ACTUAL_SCRIPT_FILE="$0"
fi
SCRIPT_DIRECTORY="$(dirname "$ACTUAL_SCRIPT_FILE")"
touch "$SCRIPT_DIRECTORY/../myFile.txt"
use .. to point to parent directory. So you could create a file using something like
MY_SCRIPTDIR="$(dirname $0)"
touch ${MY_SCRIPTDIR}/../abc.txt
From your command prompt or within shell script.
Unfortunately, the other answers either give you the current working directory instead of the directory the script is in, or they will not work if either the script or one of the directories along the way is a symbolic link rather than a real directory.
What will work is:
dirname $(readlink -f "$0")
Explanation:
"$0" is the name of the script as you type it in your command line. Quoting is important for the case it contains whitespace.
readlink will resolve any symbolic links along the way
dirname takes just the directory name from script's full path - it's better readable and safer for corner cases than manually looking for slashes etc.
Now, you will get the correct result even in a complex case: if your script is in /tmp and you create a symbolic link to it in /tmp/abc/, and your current directory will be /home and you run /tmp/abc/your-script, it will correctly output /tmp, not /home nor /tmp/abc.

Why does this script work in the current directory but fail when placed in the path?

I wish to replace my failing memory with a very small shell script.
#!/bin/sh
if ! [ –a $1.sav ]; then
mv $1 $1.sav
cp $1.sav $1
fi
nano $1
is intended to save the original version of a script. If the original has been preserved before, it skips the move-and-copy-back (and I use move-and-copy-back to preserve the original timestamp).
This works as intended if, after I make it executable with chmod I launch it from within the directory where I am editing, e.g. with
./safe.sh filename
However, when I move it into /usr/bin and then I try to run it in a different directory (without the leading ./) it fails with:
*-bash: /usr/bin/safe.sh: /bin/sh: bad interpreter: Text file busy*
My question is, when I move this script into the path (verified by echo $PATH) why does it then fail?
D'oh? Inquiring minds want to know how to make this work.
The . command is not normally used to run standalone scripts, and that seems to be what is confusing you. . is more typically used interactively to add new bindings to your environment (e.g. defining shell functions). It is also used to similar effect within scripts (e.g. to load a script "library").
Once you mark the script executable (per the comments on your question), you should be able to run it equally well from the current directory (e.g. ./safe.sh filename) or from wherever it is in the path (e.g. safe.sh filename).
You may want to remove .sh from the name, to fit with the usual conventions of command names.
BTW: I note that you mistakenly capitalize If in the script.
The error bad interpreter: Text file busy occurs if the script is open for write (see this SE question and this SF question). Make sure you don't have it open (e.g. in a editor) when attempting to run it.

Bash - cd your instance rather than sub process

So I've created a bash script that takes argument and then (I want it to) cd me into a directory.
It's not quite a case of cd /home/$1 for example, it's a bit more complex.
The problem is (as I knew it would be) it's cding the sub process rather than my instance of bash.
Is there any way to apply it to my open bash?
Echo the desired directory, then create a bash alias as follows:
alias jump="cd $(myscript.sh)"
It's the approach I use for autojump, and it works very well.
I guess this is another option for you
favorite directory

Resources