mkdir command not found in bash script - bash

I don't know why I get error while running this simple script:
#!/bin/bash
read -p "Please enter directory name: " DIR
read -p "Please enter the path: " PATH
mkdir -p "$PATH/$DIR"
line 7: mkdir: command not found

Don't use the variable PATH. This variable contains a list of directories to search for executable programs. Since you're replacing it, the script can no longer find the mkdir program.
In general, avoid using variables that are all uppercase, these are often used as parameters for the shell or other programs.

The variable PATH is an important environment variable - it is the way that programs (like mkdir) are found, and you are overwriting it. You shouldn't do that, but if you must then:
/bin/mkdir -p "$PATH/$DIR"
but honestly DON'T USE UPPERCASE! There are loads of reserved or special variables in Bash, and if you can't remember them all then just remember that all except one is in UPPERCASE. Variables in Bash are case-sensitive, like in all sensible programming languages.

Related

Bash Shell Script Issues

I am new to UNIX and have a homework assignment that is giving me trouble. I am to write a script that will back up specified files from the current directory into a specified destination directory. This script is to take three arguments.
sourcePath, which is the path to the source files/files being backed up or copied.
backupPath, which is the path to the target directory where the files will be backed up.
filePrefix, which is used to identify which files to backup, specifically only files whose names begin with the given prefix will be copied while others will be ignored. Example would be, if the user enters the letter "d", then all files starting with that letter are to be copied while any other file is to be ignored.
I haven't learned much about scripting/functions in bash so I've tried looking up tutorials which have been helpful but not enough. This script is something I can easily do when just typing out the commands. For instance, I would cd into the target directory that has the files, then using the cp command copy files that begin with the specific prefix to the target directory, but when making a script I am at a dead end.
I feel as though my code is monumentally incorrect and its due to my lack of experience, but nothing online has been of any help. So far my code is
read sourcePath
read backupPath
read filePrefix
grep /export/home/public/"$sourcePath
mkdir -p $backupPath
cp /export/home/public/"$sourcePath"/$filePrefix /home/public/"$backupPath"
So an example execution of the script would be
$ ./script.sh
(sourcePath)HW4testdir (backupPath)backup (filePrefix)d
Output:
backing up: def (example file starting with d)
backing up: dog (example file starting with d)
So far when executing the code, nothing happens. Again, I'm sure most, or even all of the code is wrong and totally off base, but I never learned about scripting. If I did not have to create a script, I could easily achieve this desired outcome.
I suggest with bash:
read -r -p "sourcePath: " sourcePath
read -r -p "backupPath: " backupPath
read -r -p "filePrefix: " filePrefix
mkdir -p /home/public/"$backupPath"
cp /export/home/public/"$sourcePath/$filePrefix"* /home/public/"$backupPath"
Make sure that the used user has the right to create the directory /home/public/"$backupPath".
See: help read
For a start: Your assignment states, that your script should accept arguments.
However your script does not take arguments. It reads the parameters from standard input. Arguments are passed to the script on the command line, and your script would be called as
./script.sh HW4testdir backup d
Hence you can't use read to fetch them. The first argument is available under the name $1, the second argument is $2 and so on. You could write for instance
sourcePath=${1?Parameter missing}
which has the side effect to abort the script with an error message, if the caller forgets to pass the parameter.
Another point: You don't say anywhere that bash should be used to run the script. Since you want the script to be called by
./script.sh ....
and not by
bash ./script.sh ....
you must encode the information, that bash should be used, in your script. Assuming that your bash is located in /usr/bin, you would do this by making the first line of the script
#!/usr/bin/bash

How do I pass a variable from AppleScript to a shell command?

So far I have:
do shell script {var}
"if [[ ! -e /$var/ ]]; then
mkdir -p $var
fi"
I am getting an error of "Command not found"
I know I need to escape something, I'm just not sure where.
Var needs to be passed to the shell command, and create the directory in the specified folder if it doesn't already exist.
All you need is, e.g.:
set var to "/path/to/directory/subdirectory"
do shell script "mkdir -p " & var's quoted form
You do not need to test whether of not it already exists because of the use of the -p option with the mkdir command.
From the manual page for mkdir:
-p Create intermediate directories as required. If this option is not specified, the full path
prefix of each operand must already exist. On the other hand, with this option specified, no
error will be reported if a directory given as an operand already exists. Intermediate
directories are created with permission bits of rwxrwxrwx (0777) as modified by the current
umask, plus write and search permission for the owner.

bash script doesn't find mkdir [duplicate]

This question already has answers here:
Getting "command not found" error in bash script
(6 answers)
Closed 2 years ago.
I've created a simple script to check if a folder exists and if not to create it. The script that follow
#!/bin/bash
PATH=~/Dropbox/Web_Development/
FOLDER=Test
if [ ! -d $PATH$FOLDER ]
then
echo $PATH$FOLDER 'not exists'
/bin/mkdir $PATH$FOLDER
echo $PATH$FOLDER 'has been created'
fi
works only if the mkdir command is preceded by /bin/. Failing in that, bash env output the error message "command cannot be found".
I though this could have been related to the system $PATH variable, but it looks regular (to me) and the output is as following:
/Library/Frameworks/Python.framework/Versions/2.7/bin:/bin:/usr/local/bin:/usr/bin:/sbin:/usr/local/sbin:/usr/sbin
I'm not sure whether the order with the different bin folders have been listed make any difference, but the /bin one (where the mkdir on my OSX Maverick) seems to reside is there hence I would expect bash to being able to execute this.
In fact, if I call the bash command from terminal, by typing just mkdir bash output the help string to suggest me how the mkdir command should be used. This suggests me that at a first instance bash is able to recognise the $PATH variable.
So what could be the cause? Is there any relation between the opening statement at the top of my .sh - #!/bin/bash - file and the "default" folder?
Thanks
Yeah, sometimes it is a bad idea to use capital letters for constant variables, because there are some default ones using the same convention. You can see some of the default variables here (Scroll to Special Parameters and Variables section). So it is better to use long names if you don't want to get any clashes.
Another thing to note is that you're trying to replicate mkdir -p functionality, which creates a folder if it does not exist (also it does create all of the parents, which is what you need in most cases)
One more thing - you always have to quote variables, otherwise they get expanded. This may lead to some serious problems. Imagine that
fileToRemove='*'
rm $fileToRemove
This code will remove all files in the current folder, not a file named * as you might expect.
One more thing, you should separate path from a folder with /. Like this "$MY_PATH/$MY_FOLDER". That should be done in case you forget to include / character in your path variable. It does not hurt to have two slashes, that means that /home/////////user/// folder is exactly the same /home/user/ folder.
Sometimes it is tricky to get ~ working, so using $HOME is a bit safer and more readable anyway.
So here is your modified script:
#!/bin/bash
MY_PATH="$HOME/Dropbox/Web_Development/"
MY_FOLDER='Test'
mkdir -p "$MY_PATH/$MY_FOLDER"
The problem is that your script sets PATH to a single directory, and that single directory does not contain a program called mkdir.
Do not use PATH as the name of a variable (use it to list the directories to be searched for commands).
Do learn the list of standard environment variable names and those specific to the shell you use (e.g. bash shell variables). Or use a simple heuristic: reserved names are in upper-case, so use lower-case names for variables local to a script. (Most environment variables are in upper-case — standard or not standard.)
And you can simply ensure that the directory exists by using:
mkdir -p ~/Dropbox/Web_Development
If it already exists, no harm is done. If it does not exist, it is created, and any other directories needed on the path to the directory (eg ~/Dropbox) is also created if that is missing.

Deleting a directory contents using shell scripts

I am a newbie to Shell scripting. I want to delete all the contents of a directory which is in HOME directory of the user and deleting some files which are matching with my conditions. After googled for some time, i have created the following script.
#!/bin/bash
#!/sbin/fuser
PATH="$HOME/di"
echo "$PATH";
if [ -d $PATH ]
then
rm -r $PATH/*
fuser -kavf $PATH/.n*
rm -rf $PATH/.store
echo 'File deleted successfully :)'
fi
If I run the script, i am getting error as follows,
/users/dinesh/di
dinesh: line 11: rm: command not found
dinesh: line 12: fuser: command not found
dinesh: line 13: rm: command not found
File deleted successfully :)
Can anybody help me with this?
Thanks in advance.
You are modifying PATH variable, which is used by the OS defines the path to find the utilities (so that you can invoke it without having to type the full path to the binary). The system cannot find rm and fuser in the folders currently specified by PATH (since you overwritten it with the directory to be deleted), so it prints the error.
tl;dr DO NOT use PATH as your own variable name.
PATH is a special variable that controls where the system looks for command executables (like rm, fuser, etc). When you set it to /users/dinesh/di, it then looks there for all subsequent commands, and (of course) can't find them. Solution: use a different variable name. Actually, I'd recommend using lowercase variables in shell scripts -- there are a number of uppercase reserved variable names, and if you try to use any of them you're going to have trouble. Sticking to lowercase is an easy way to avoid this.
BTW, in general it's best to enclose variables in double-quotes whenever you use them, to avoid trouble with some parsing the shell does after replacing them. For example, use [ -d "$path" ] instead of [ -d $path ]. $path/* is a bit more complicated, since the * won't work inside quotes. Solution: rm -r "$path"/*.
Random other notes: the #!/sbin/fuser line isn't doing anything. Only the first line of the script can act as a shebang. Also, don't bother putting ; at the end of lines in shell scripts.
#!/bin/bash
path="$HOME/di"
echo "$path"
if [ -d "$path" ]
then
rm -r "$path"/*
fuser -kavf "$path"/.n*
rm -rf "$path/.store"
echo 'File deleted successfully :)'
fi
This line:
PATH="$HOME/di"
removes all the standard directories from your PATH (so commands such as rm that are normally found in /bin or /usr/bin are 'missing'). You should write:
PATH="$HOME/di:$PATH"
This keeps what was already in $PATH, but puts $HOME/di ahead of that. It means that if you have a custom command in that directory, it will be invoked instead of the standard one in /usr/bin or wherever.
If your intention is to remove the directory $HOME/di, then you should not be using $PATH as your variable. You could use $path; variable names are case sensitive. Or you could use $dir or any of a myriad other names. You do need to be aware of the key environment variables and avoid clobbering or misusing them. Of the key environment variables, $PATH is one of the most key ($HOME is another; actually, after those two, most of the rest are relatively less important). Conventionally, upper case names are reserved for environment variables; use lower case names for local variables in a script.

How to run my own programm using command in Shell?

I just learned that I could use chmod make myscript.sh executable and the run it as $ ./myscript.sh But how can I attach a custom command to it, like $ connectme [options] ?
You need to do two things:
Give the name you want to use. Either just rename it, or establish a link (hard or symbolic). Make sure the correctly named object has the right permissions.
Make sure it is in you path. But putting "." in you PATH is a bad idea (tm), so copy it to $HOME/bin, and put that in you path.
A completely different approach. Most shells support aliases. You could define one to run your script.
Note: The environment variable PATH tells the shell where to look for programs to run (unless you specify a fully qualified path like /home/jdoe/scripts/myscript.sh or ./myscript.sh), it consists of a ":" seperated list of directories to examine. You can check yours with:
$ printenv PATH
resulting for me in
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11/bin:/usr/X11R6/bin
which are the usual directories for binaries. You can add a new path element with (in /bin/sh and derivatives):
$ export PATH=$PATH:$HOME/bin
in csh and derivatives use
$ setenv PATH $PATH:$HOME/bin
either of which which will result in the shell also searching ~/bin for things to run. Then move your script into that directory (giving ta new name if you want). Check that you execute permissions for the script, and just type its name like any other command.
Fianlly, the use of a ".sh" extension to denote a shell script is for human consumption only. Unix does not care about how you name your script: it is the so-called "shebang" ("#!") on the first line of the script that the OS uses to find the interpreter.
You need to learn about arguments in BASH PROGRAMMING. Here is a good tutorial on them. Check section #4 out.
Basically, you need to use special variables $1, $2, $3 to refer to first, second and third command line arguments respectively.
Example:
$ ./mycript.sh A-Rod
With myscript.sh being:
#!/bin/bash
echo "Hello $1"
Will print:
Hello A-Rod

Resources