This question already has answers here:
How do I prompt for Yes/No/Cancel input in a Linux shell script?
(37 answers)
Closed 3 years ago.
I'm currently learning Unix and have come across a question in a book that I'm trying to solve.
I'm trying to write a script that asks a user to enter a file name.
Then, the script needs to check for file existence. If the file does not exist, that script should display an error message and then exit the script.
If the file exists, the script should ask if the user wants to delete the file:
If the answer is yes or y, the script should remove the file.
If the answer is no or n, the script should exit from the script.
If the answer is neither yes nor no, the script should display an error message and exit from the script.
This what I have written so far but have come across with a few errors:
#!/bin/bash
file=$1
if [ -f $file ];
then
echo read -p "File $file existes,do you want to delete y/n" delete
case $delete in
n)
exit
y) rm $file echo "file deleted";;
else
echo "fie $file does not exist"
exit
fi
If anyone come explain where I have gone wrong it would be greatly appreciated
I'd suggest this form:
#!/bin/bash
file=$1
if [[ -f $file ]]; then
read -p "File $file exists. Do you want to delete? [y/n] " delete
if [[ $delete == [yY] ]]; then ## Only delete the file if y or Y is pressed. Any other key would cancel it. It's safer this way.
rm "$file" && echo "File deleted." ## Only echo "File deleted." if it was actually deleted and no error has happened. rm probably would send its own error info if it fails.
fi
else
echo "File $file does not exist."
fi
Also you can add -n option to your prompt to just accept one key and no longer require the enter key:
read -n1 -p "File $file exists. Do you want to delete? [y/n] " delete
You added echo before read and I removed it.
In it's simplest form, you could do the following:
$ rm -vi file
To give you an example:
$ mkdir testdir; touch testdir/foo; cd testdir; ls
foo
$ rm -vi bar
rm: cannot remove 'bar': No such file or directory
$ rm -vi foo
rm: remove regular empty file 'foo'? y
removed 'foo'
Related
Is there a way to check the user's response to a rm -i execution?
I'd like to echo something depending on whether or not the user responded with y or n.
The command returns successfully regardless of the user's response, so this attempt did not work:
$ rm -i testfile.txt && echo "The file was deleted."
remove testfile.txt? n
The file was deleted.
My reasoning was that the echo part would only be executed if the rm part was successful, but obviously a n response also counts as successful execution.
I would also like to be able to vary the message depending on the answer. This code would do it, but it's not very pretty.
file=testfile.txt
touch $file
read -p "Are you sure (y/n)? " answer
if [[ $answer =~ ^[yY](es|ES)?$ ]]; then
rm $file
echo "Deleted file."
else
echo "Did nothing."
fi
Surely there must be a way to get the input to rm -i.
How?
You can check, if the file was actually deleted. Eg.
rm -i testfile.txt && [[ ! -e testfile.txt ]] && echo "The file was deleted."
If the rm is successful, then test, if the file does not exist [[ ! -e file ]] and only then display the message. It covers the case, when you try to remove the file that does not exist, since then the rm will return with the exit code different than 0.
In case you want to display messages for when the file was purposefully deleted or not deleted, plus extra info on error, then you can extend the previous code like so:
rm -i testfile.txt && {
[[ ! -e testfile.txt ]] && echo "The file was deleted." || echo "Ignored"
} || echo "Error"
Most of the problem with your attempt is that you are trying to accommodate too many possible inputs, or paradoxically limiting the input to specifically "yes" or "no" while excluding "yeah", "yup", "nope", etc. A simply y or n will do (in fact, the only distinction you need to make is between y and not-y).
read -p "Are you sure (y/n)? " answer
if [[ $answer = [yY]* ]]; then
rm -- "$file"
echo "Deleted file."
else
echo "Did nothing."
fi
If you like, you can use shopt -s nocasematch before the if statement so that you can simply write if [[ $answer = y* ]]; then to ignore the case of the user's actual input.
Your original question would require some hook provided by rm itself, which it does not do.
This question already has answers here:
Check if a file exists with a wildcard in a shell script [duplicate]
(21 answers)
Closed 3 years ago.
I want to check if file exists but only checking if some the filename exists
For example in some folder I have these files (Date format: AAAAMMDD):
Rejets_20190112.csv.zip
Rejets_20190312.csv.zip
Rejets_20190314.csv.zip
I want to check if there is a file that begins with Rejet_DAP_201903 exists in that folder. In other word I want to check if Rejet_DAP file with current year and month exist, the day doesn't matter.
Here's what I tried to do in my script:
jour=`date +%d`
mois=`date +%m`
annee=`date +%Y`
FILE="/appli/project/echanges/RTY/receptions/Rejet_${annee}${mois}"_*
if [[ -e $FILE ]]
then
echo "FILE EXISTS"
else
echo "FILE DOES NOT EXIST"
fi
You have the directory path and the file pattern that you are looking for.
The ls command can be used to list files based on patterns.
All commands return an integer value after execution. 0 means the execution finished successfully. Any non-zero value means error.
ls will return a non-zero value if no files match the pattern.
That return code you can use within the if statement.
#!/bin/bash
jour=`date +%d`
mois=`date +%m`
annee=`date +%Y`
/appli/project/echanges
dir="/appli/project/echanges/RTY/receptions"
file_prefix="Rejet_DAP_"
if ls $dir/${file_prefix}${annee}${mois}* > /dev/null 2>&1
then
echo "FILE EXISTS"
else
echo "FILE DOES NOT EXIST"
fi
The #!/bin/bash line is called a shebang line and I highly recommend using it in your scripts.
The > /dev/null 2>&1 is so that you don't get output from the ls command and only have your output displayed.
You can use find for this
$ if [[ `find /appli/project/echanges/RTY/receptions/ -type f |grep -i Rejet_DAP_${annee}${mois}|wc -l` -gt 0 ]] ; then
echo "FILE EXISTS"
else
echo "FILE DOES NOT EXIST"
fi
This question already has answers here:
How do I prompt for Yes/No/Cancel input in a Linux shell script?
(37 answers)
How do I tell if a file does not exist in Bash?
(20 answers)
Closed 5 years ago.
#!/bin/bash
filename=../deleted/$1
#Testing condition before deletion of file
if [ "$1" = "" ] ; then
echo "No filename provided"
elif [ -f "../deleted/$1" ] ; then
echo "File doesnot exist"
str=$(fgrep "$1" ../.restore.info | cut -d ":" -f2)
path=${str%/*}
mv "../deleted/$1" "${path}"
newname=$(fgrep "$1" ../.restore.info | cut -d "_" -f1)
mv -i "$1" "${newname}"
else
echo "file does not exist"
fi
----------
( I have written script to move file from the deleted folder to its original path and its working fine. But now i have to check if there is already a file with same name then it should give alert user "do u want to overwrite " if yes then overwrite if no or anything else then do not restore)
Source: http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html
if [[ -e "$newname" ]]; then
read -p "Overwrite? [y,N]" overwrite
if [[ "$overwrite" = [Y,y] ]]; then
mv -i "$1" "${newname}"
fi
fi
The -e flag will simply check if it exists. (you can use the -f as you did above or -r to see if it exists and is readable.) The read command will prompt the user with the text in between the quotes and store it in the variable. The last if will only move the file if they input Y or y. (I didn't include it but you could easily add an else if to say not moved if they select no and also an else for an invalid response should you choose in the second if.)
(Not infront of my machine so I could not test it, but I am pretty sure all my syntax is correct. Let me know if not tho.)
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.
I'm trying to compile a script that will read user input, and check if the file after the y/n statement. Then it will make files executable. I think the problem with my script is conditional ordering but check it out yourself:
target=/home/user/bin/
cd $target
read -p "This will make the command executable. Are you sure? (y/n)" CONT
if [ "$CONT" == "y" ];
then
chmod +x $1
echo "File $1 is now executable."
else
if [ "$(ls -A /home/user/bin/)" ];
then
echo "File not found."
else
echo "Terminating..."
fi
fi
As I said, I need the script to scan for the file after the y/n statement is printed. The script works fine how it is but still gives the "file is now executable" even if the argument file doesn't exist (but just gives the standard system "cannot find file" message after the echo'd text).
Your script is mostly correct, you just need to check if the file exists first. Also, it's not the best practice to use cd in shell scripts and not needed here.
So re-writing it
#!/bin/bash
target="/home/user/bin/$1"
if [[ ! -f $target ]]; then
echo "File not found."
else
read -p "This will make the command executable. Are you sure? (y/n) " CONT
if [[ $CONT == "y" ]]; then
chmod +x "$target"
echo "File $1 is now executable."
else
echo "Terminating..."
fi
fi
To get an understanding:
Your script will take one argument (a name of a file).
You ask if you want to make that file executable.
If the answer is 'yes', you make the file executable.
Otherwise, you don't.
You want to verify that the file exists too?
I'm trying to understand your logic. What does this:
if [ "$(ls -A /home/user/bin/)" ];
suppose to do. The [ ... ] syntax is a test. And, it has to be one of the valid tests you see here. For example, There's a test:
-e file: True if file exists.
That mean, I can see if your file is under /home/user/bin:
target="/home/user/bin"
if [ -e "$target/$file" ] # The "-e" test for existence
then
echo "Hey! $file exists in the $target directory. I can make it executable."
else
echo "Sorry, $file is not in the $target directory. Can't touch it."
fi
Your $(ls -A /home/user/bin/) will produce a file listing. It's not a valid test like -e unless it just so happens that the first file in your listing is something like -e or -d.
Try to clarify what you want to do. I think this is something more along the lines you want:
#! /bin/bash
target="/home/user/bin"
if [ -z "$1" ] # Did the user give you a parameter
then
echo "No file name given"
exit 2
fi
# File given, see if it exists in $target directory
if [ ! -e "$target/$1" ]
then
echo "File '$target/$1' does not exist."
exit 2
fi
# File was given and exists in the $target directory
read -p"Do you want $target/$1 to be executable? (y/n)" continue
if [ "y" = "$continue" ]
then
chmod +x "$target/$1"
fi
Note how I'm using the testing, and if the testing fails, I simply exit the program. This way, I don't have to keep embedding if/then statements in if/then statements.