How do I create a Bash script that takes a file name as input? Then, if that file exists, it should print "File exists"; if not, print "File does not exist".
For example, if I ran ./do-i-exist.sh ./do-i-exist.sh, the output should be only 'File exists'
file="$1"
read answer
if [ $file != -$2 ]
then
echo "File exists"
else
echo "File does not exist"
fi
This is what I'm working with but is not working for me, whenever I add an extension like .sh, .txt or something similar it won't find the file.
The test if a file exists can be done like this
if [ -f "$file" ]
then
This tests for a regular file, not for other kinds of files like a directory.
This is how you can do it. Pass the name of the file while like ./do-i-exist.sh file_path.
if [ -f "$1" ]
then
echo "File Exists"
else
echo "File does not exist"
fi
First of all, I want to thank anyone and everyone who tried to help. After 3 hard working days, I found the answer, here it is:
#!/bin/bash
file="$#"
if [ -f $file ]
then
echo "File exists"
else
echo "File does not exist"
fi
Using this table:
Variable Name
Description
$0
The name of the Bash script
$1 - $9
The first 9 arguments to the Bash script
$#
Number of arguments passed to the Bash script
$#
All arguments passed to the Bash script
$?
The exit status of the most recently run process
$$
The process ID of the current script
$USER
The username of the user running the script
$HOSTNAME
The hostname of the machine
$RANDOM
A random number
$LINENO
The current line number in the script
I and other users were focused on using $1 from my understanding this refers to the first argument passed to the script but for some reason, it wasn't working since it needed to pass more inputs.
As from my previous comments I didn't have control over the input. The input was hidden in a locked file, and I needed to feed my script to it.
From what we know $0 is only used to check for the file names, $1 to get the first statement and $# will just take anything(I guess).
I know absolutely nothing about bash and it was the first time ever using it, which is why it took me 3 days to solve this puzzle. This was part of a CTF and just like me, many others may struggle in the future to understand or know how to make a script that will just adapt to a series of inputs from a second script.
This is how it was supported to work:
I was given access to a very restricted server and on this server, I was given the encrypted-file.sh file. This file was supposed to be fed to /path/to/myfile.sh then encrypted-file.sh would execute a second command to open a third locked file hiding a flag on it.
This only works with the right bash file using the right variables on it for encrypted-file.sh to run without errors, which is what I accomplished here.
I used a while loop because it made sense in my case because I really needed a file for the script to work.
restore_file="$1"
while [ ! -f "$restore_file" ]
do
echo "File not found: $restore_file"
echo "Please provide a valid file:"
read restore_file
done
As written above, $1 is the first argument given to the script. In this case if no argument is given or that is not a file, it will prompt again.
By the way, use -d instead of -f to check for a directory.
Related
Im writing a data formating bash script. The script reads the file name which is input by the user in the terminal. Of course, when no file under that name is found in that directory, the program ends with a stderr output. I am now trying to implement a (while) loop which recursively asks for user input until a matching file is found and then goes on to executing my data formating commands. Would appreciate some help :)
I am now trying to implement a (while) loop which recursively
I would advice against using recursion for this. Just make a simple loop. It could look like this:
while true; do
IFS= read -rp 'File: ' file
if [[ -e $file ]]; then
break;
fi
echo "$file doesn't exist, try again"
done
# work with $file here
I'm writing a bash script to organise a .txt file, of which is loaded with the bash script using the command line parameter:
bash ./myScript.sh textfile.txt
I have an if statement (below, non-functional) that's supposed to detect if the .txt file exists in the same directory. If it does, it confirms it with the user and the script continues. If it doesn't exist, the script is supposed to continually check if the user's input is an existing file in the working directory before continuing.
Here's what I have so far:
#CS101 Assignment BASH script
CARFILE=$1
wc $CARFILE
if [ -f $CARFILE ]
then
echo "$CARFILE exists, please continue"
else
echo "This file does not exist, please enter the new filename and press [ENTER]"
read CARFILE
echo "We have detected that you're using $CARFILE as your cars file, please continue."
fi
It simply outputs: exists, please continue if you don't run it with a .txt (ie bash jag32.sh instead of bash jag32.sh textfile.txt).
Can anyone help out please?
Thanks.
There are two problems here. First, you're calling wc $CARFILE before you check if $CARFILE exists. If you specify no paramaters (bash jag32.sh), then this becomes simply wc, which will wait forever for input on stdin.
Before going any further, bash -x is your friend: this will trace the execution of your script, showing you exactly what commands the script is running. This will often help illuminate problems:
bash -x jag32.sh
The problem with your test:
if [ -f $CARFILE ]
Is that if $CARFILE is empty, it becomes simply:
if [ -f ]
Which evaluates to true. What!? That's because the file-existence test takes two parameters (-f FILE), and when $CARFILE is empty, you only have one, so it's evaluating as a simple is-this-string-empty? test.
And this is why you always quote variables:
if [ -f "$CARFILE" ]
If $CARFILE is empty, this becomes:
if [ -f "" ]
Which will evaluate to false.
In addition to checking for the existence of the file, you could also first check if $1 has any value, or if your script has been passed any arguments. The bash(1) and test(1) man pages have details that should point you in the right direction.
I am not a great bash scripter and hence have a few questions. One of which is how (or even whether) bash understands that a variable is a "file" or simply a local variable.
file=/usr/share/lib
Obviously this is a file to be saved, etc and can be used like so:
echo "$output" > $file
To save the output of $output to $file.
But where in bash does it calculate whether it's a file or not, is it only a file once it's been passed to a 'writing method'?
If you treat that variable as a file name, bash will simply do what it's told e.g.
echo "Test output" > $file
will work regardless of file being set to /tmp/myfile.txt, or to abcd. In the above you're using bash's file redirection to write out the standard out to the file you've named.
Consequently if you use the wrong variable in the above pattern, or have the value set incorrectly, bash will simply follow your instructions and you may end up with incorrectly named/located files.
You need to check this yourself, bash is only aware of the contents of the variable. If you want to check if a file location is held within a variable, you can test for it using the -f test operator
if [ -f "$file" ]
then
echo "$file is a file"
echo "$output" > "$file"
else
echo "$file is not a file"
fi
Variables are strings - nothing more, nothing less. (I'm ignoring array variables here, WLOG).
Bash (or any shell) expands variables blindly, without considering what you intend to do with them. It's only in the next stage of command processing that the contents of the string matter.
To use your example:
output="foo bar"
file=/usr/share/lib
echo "$output" >"$file"
(I've quoted $file even though it's not necessary here, simply because I've been bitten too many times by changing the value and breaking everything).
The line
echo "$output" >"$file"
gets transformed into
echo "foo bar" >"/usr/share/lib"
and only then does bash consider the > and attempt to open /usr/share/lib for writing.
I am writing a batch-processing script bash that needs to first check to see if a folder exists to know whether or not to run a certain python script that will create and populate the folder. I have done similar things before that do fine with changing the directories and finding directories from a stored variable, but for some reason I am just missing something here.
Here is roughly how the script is working.
if [ -d "$net_output" ]
then
echo "directory exists"
else
echo "directory does not exist"
fi
when I run this script, I usually echo $net_output in the line before to see what it will evaluate to. When the script runs I get my else block of code saying "Directory does not exist", but when I then copy and paste the $net_output directory path that is echoed before into the shell terminal, it changes directories just fine, proving that the directory does in fact exist. I am using Ubuntu 12.04 on a Dell machine.
Thank you in advance for any help that someone can offer. Let me know what additional information I can provide.
The most common cases I've encountered when someone posts a problem like this are the following:
1. The variable contains literal quotes. Bash does not recursively parse quotes, it only parses the "outer" quotes given on the command line.
$ mkdir "/tmp/dir with spaces"
$ var='"/tmp/dir with spaces"'
$ echo "$var"
"/tmp/dir with spaces"
$ [ -d "/tmp/dir with spaces" ]; echo $?
0
$ [ -d "$var" ]; echo $? # equivalent to [ -d '"/tmp/dir with spaces"' ]
1
2. The variable contains a relative path, and the current directory is not what you expected. Check that the value of echo "$PWD" outputs what you expected.
3. The variable was read from a file with dos line endings, CRLF (\r\n). Unix and unix-like systems use just LF (\n) for line endings. If that's the case, the path will contain a CR (\r) at the end. A CR at the end of a line will be "invisible" in a terminal. Check with printf '%q\n' "$var" while debugging the script. See BashFAQ 52 on how to get rid of them.
Recently i got an assignment at school, where we are to write a small program in Bash Scripting Language.
This shell script is supposed to accept some Positional Parameters or Arguments on the command line.
Now, with the help of an if-else statement i check if the argument is present, if the argument is present the script does what it is supposed to do, but if the argument is not present - i display an error message, prompting the user to input an argument and pass the argument again to the same shell script...
Now, i want to know if this approach is good or bad in Bash Programming paradigm. I'm slightly suspicious that this might run too many tasks in the background that are kept open or that are never ended and keep on consuming memory... please help.
Here's a small snippet (assume the script name to be script1.bash):
#!/bin/bash
if [ $# -gt 0 ]; then
read -p "Please enter your name: " name
script1.bash $name
elif [ $# -eq 1 ]; then
echo "Your name is $1!"
fi
It's ... questionable :-)
The main problem is that you're spawning a subshell everytime someone refuses to input their name.
You would be better of with something like:
#!/bin/bash
name=$1
while [[ -z "$name" ]] ; do
read -p "Please enter your name: " name
done
echo "Your name is $name!"
which spawns no subshells.