Bash - Read response to copy files or directory - bash

I'm trying to write a shell script to copy a file based on user response. An example of what I am trying to do:
#!/bin/bash
echo "What is the name of the user?: "
read RESPONSE
cp /home/$RESPONSE/file.txt /home/$RESPONSE/backup/file_backup.txt
However, my copy command doesn't seem to be accepting the read variable correctly.
What am I doing wrong?

I figured out the issue. I had some commands in between and then had a second read RESPONSE command that was not required. In other words, as an example, I had this:
#!/bin/bash
echo "What is the name of the user?: "
read RESPONSE
rsync -a /home/$RESPONSE /backup
read RESPONSE
cp /home/$RESPONSE/file.txt /home/$RESPONSE/backup/file_backup.txt
Also,#GeorgeVasiliou had it right, I needed to also include it in quotes. So what works is:
#!/bin/bash
echo "What is the name of the user?: "
read response
rsync -a "/home/$response/" /backup
cp "/home/$response/file.txt" "/home/$response/backup/file_backup.txt"

The following code achieves what you want. It also checks to see if the user exists, and if the user has created a /backup/ folder before attempting to save the file (if user doesn't exist, then /home/user/... should also not exist and the script would fail).
#!/bin/bash
echo "What is the name of the user?: "
read response
checkuser1="$(getent passwd | cut -d: -f1 | grep -si "$response")"
if [ -z "$checkuser1" ]; then echo "No user with this name has been located!"; exit; fi
if [ ! -d /home/"$response"/backup/ ]; then echo "This user has not created the /home/"$response"/backup/ folder yet!"; exit; fi
cp /home/"$response"/file.txt /home/"$response"/backup/file_backup.txt
exit
Edit: the code above was edited to add a few improvements.

Related

How to get a list of subdirectories from a file and then create those subdirectories in a directory?

When a user inputs a name, there should be a new directory that gets created under that name.
In addition to that, the script needs to consult a file structure1.txt which is found in /etc/scriptbuilder/str1.
In this file, it will list two subdirectories (one on each line), the script is then supposed to create these two subdirectories in the new directory the user just made and named.
So how can the script then create each of the subdirectories that are listed in this text file?
I'm completely lost on that part.
This is my code so far:
echo "Enter the project name "
read name
echo $name
if [ ! -d $name ] then
mkdir $name
else
echo "The project name you entered already exists"
fi
cp /etc/scriptbuilder/str1/structure1.txt /$name
#I know this is wrong
because this would just copy the file over to the new directory but not actually
make the two subdirectories that are on the file onto the new directory
The bash command that you are looking for is read.
Also the syntax for your if [ ! -d "$name" ] should have a semicolon.
The else would typically have an exit 1 (or some such value).
Typical bash code gets input from the command line, but what you want is fine.
For testing purposes, I inserted a ~ (tilde), which references your home directory.
The script should look something like:
filename="/etc/scriptbuilder/str1"
read -p "Enter the project name " name
echo "$name"
if [ ! -d ~/"$name" ]; then
mkdir ~/"$name"
else
echo "The project name you entered already exists"
exit 1
fi
while read -r line; do
mkdir ~/"$name/$line"
done < "$filename"
You can clean up the formatting.

Where does if look for files in BASH

I'm wondering how to control where my if statements find files.
The code if [ -e filename ] should find a file, but where is it looking?
I have the following code I'm having trouble with:
#!/bin/bash
#create a new file
echo "Enter the customer data"
read -p "Email:" cemail
read -p "Name:" cname
read -p "Apt:" capt
read -p "Monthly Rent:" crent
read -p "Rent Due Date:" cdatedue
echo "$cemail"
#if its already a file then error
if [ -e "$cemail" ]
then
echo "Error: customer already exists"
exit 1
else
echo "ok"
fi
when I type in a filename that does exist it still isn't finding it. Our programs are in the
:~/courses/cs3423/2017Fa/Proj1 folder and the files we are searching against are in the
:~/courses/cs3423/2017Fa/Proj1/Data folder. And this is how the program has to be set up as well. How can I manipulate the if to function correctly, or do I need to use something else? Thanks.

2nd loop inside the script or asking to enter value

I have written a code but I am having a problem to make the double loop in my bash script. This script should read all the files 1 by 1 in the given directory to upload but the value of "XYZ" changes for each file. Is there a way for me to make the code ask me to enter the "XYZ" every time it reads a new file to upload? (if possible with the name of the file read) like "please enter the XYZ value of 'read file's name'" I could not think of any possible ways of doing so. I also have the XYZ values listed in a file in a different directory so maybe can it be called like the do loop I did for the path? I might actually need to use both cases as well...
#!/bin/bash
FILES=/home/user/downloads/files/
for f in $FILES
do
curl -F pitch=9 -F Name='astn' -F
"path=#/home/user/downloads/files;$f" -F "pass 1234" -F "XYZ= 1.2" -
F time=30 -F outputFormat=json
"http://blablabla.com"
done
try following once.
#!/bin/bash
FILES=/home/user/downloads/files/
for f in $FILES
do
echo "Please enter the name variable value here:"
read Name
curl -F pitch=9 -F "$Name" -F
"path=#/home/user/downloads/files;$f" -F "pass 1234" -F "XYZ= 1.2" -
F time=30 -F outputFormat=json
"http://blablabla.com"
done
I have entered a read command inside loop so each time it will prompt user for a value, since you haven't provided more details about your requirement so I haven't tested it completely.
The problem was actually the argument. By changing it to:
-F Name="$Name"
solved the problem. Trying to link the argument such as only $Name or "$Name" causes a bad reception.

How do I combine an "if" and a "while loop" statement together?

New to shell scripting and I want to test to see if the variables I created are valid directories and if not send the user into a while loop to enter the directory and only allow exit when a valid directory is entered.
So far this is what my script looks like:
~/bin/bash
source_dir="$1"
dest_dir="$2"
mkdir /#HOME/$source_dir
mkdir /#HOME$dest_dir
if [ -d "$source_dir" ]
then
echo "$source_dir is a valid directory"
fi
while [[ ! -d "$source_dir" ]]
do
echo "Please enter a valid directory"
read source_dir
done
Is there any way to combine these into a single statement?
The while code will never execute if the directory is valid. Therefore just move the echo "$source_dir is a valid directory" after the loop:
#!/bin/bash
source_dir="$1"
dest_dir="$2"
mkdir "$HOME/$source_dir"
mkdir "$HOME/$dest_dir"
until [[ -d "$source_dir" ]]
do
read -p "Please enter a valid directory" source_dir
done
echo "$source_dir is a valid directory"
Notes:
a few code typos were fixed, e.g. /#HOME$dest_dir should be "$HOME/$dest_dir".
any while ! can be shortened to until.
The above code lacks a few things:
It tries create a new dir, then if that fails, has the user enter an already existing directory. It might be better to let the user create a new directory, but only if it doesn't already exist.
It would be better to check if $dest_dir exists.
Here's a more thorough approach using a shell function:
#!/bin/bash
untilmkdir ()
{
d="$1";
until mkdir "$d" ; do
read -p "Please enter a valid directory: " d
[ -d "$d" ] && break
done;
echo "$d is a valid directory" 1>&2
echo "$d"
}
source_dir=$(untilmkdir "$HOME/$1")
dest_dir=$(untilmkdir "$HOME/$2")
Notes:
The prompts in untilmkdir are printed to stderr.
The name of whatever directory untilmkdir creates is printed to stdout.
Having untilmkdir print to both stderr and stdout allows storing the successfully created name to a variable.

bash save last user input value permanently in the script itself

Is it possible to save last entered value of a variable by the user in the bash script itself so that I reuse value the next time while executing again?.
Eg:
#!/bin/bash
if [ -d "/opt/test" ]; then
echo "Enter path:"
read path
p=$path
else
.....
........
fi
The above script is just a sample example I wanted to give(which may be wrong), is it possible if I want to save the value of p permanently in the script itself to so that I use it somewhere later in the script even when the script is re-executed?.
EDIT:
I am already using sed to overwrite the lines in the script while executing, this method works but this is not at all good practice as said. Replacing the lines in the same file as said in the below answer is much better than what I am using like the one below:
...
....
PATH=""; #This is line no 7
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )";
name="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")";
...
if [ condition ]
fi
path=$path
sed -i '7s|.*|PATH='$path';|' $DIR/$name;
Someting like this should do the asked stuff :
#!/bin/bash
ENTERED_PATH=""
if [ "$ENTERED_PATH" = "" ]; then
echo "Enter path"
read path
ENTERED_PATH=$path
sed -i 's/ENTERED_PATH=""/ENTERED_PATH='$path'/g' $0
fi
This script will ask user a path only if not previously ENTERED_PATH were defined, and store it directly into the current file with the sed line.
Maybe a safer way to do this, would be to write a config file somewhere with the data you want to save and source it . data.saved at the begining of your script.
In the script itself? Yes with sed but it's not advisable.
#!/bin/bash
test='0'
echo "test currently is: $test";
test=`expr $test + 1`
echo "changing test to: $test"
sed -i "s/test='[0-9]*'/test='$test'/" $0
Preferable method:
Try saving the value in a seperate file you can easily do a
myvar=`cat varfile.txt`
And whatever was in the file is not in your variable.
I would suggest using the /tmp/ dir to store the file in.
Another option would be to save the value as an extended attribute attached to the script file. This has many of the same problems as editing the script's contents (permissions issues, weird for multiple users, etc) plus a few of its own (not supported on all filesystems...), but IMHO it's not quite as ugly as rewriting the script itself (a config file really is a better option).
I don't use Linux, but I think the relevant commands would be something like this:
path="$(getfattr --only-values -n "user.saved_path" "${BASH_SOURCE[0]}")"
if [[ -z "$path" ]]; then
read -p "Enter path:" path
setfattr -n "user.saved_path" -v "$path" "${BASH_SOURCE[0]}"
fi

Resources