How to write a shell script which creates a file
echo "Enter the file you want to create"
read a
touch $a
And adds content to the created file 'a'
echo "Enter the contents to your $a file:"
cat > $a << 'EOF'
EOF
The above one is not the right way, what I am doing wrong here ?
You were almost there. This will do what you ask:
echo "Enter the file you want to create"
read a
echo "Enter the contents to your $a file (press ctrl-D when done):"
cat >"$a"
Discussion
touch $a
It is not necessary to touch the file. The cat statement will create it regardless.
Also, because file names can include whitespace, it is best to put inside double-quotes any shell variable containing a file name. This prevents word splitting.
cat > $a << 'EOF'
EOF
The construct << 'EOF' tells the shell to read from a here document. This is what you use if you have text in your shell script that you want to use as input. You don't. You want instead to read input from the user. Thus the above two lines can be simply replaced with cat >"$a" .
You can ask then proceed with a simple echo:
echo "Enter the file you want to create"
read file
echo "Enter the contents to your $a file:"
read content
echo "$content" > "$file"
Related
I need to add new lines with specific information to one or multiple files at the same time.
I tried to automate this task using the following script:
for i in /apps/data/FILE*
do
echo "nice weather 20190830 friday" >> $i
done
It does the job yet I wish I can automate it more and let the script ask me for to provide the file name and the line I want to add.
I expect the output to be like
enter file name : file01
enter line to add : IWISHIKNOW HOWTODOTHAT
Thank you everyone.
In order to read user input you can use
read user_input_file
read user_input_text
read user_input_line
You can print before the question as you like with echo -n:
echo -n "enter file name : "
read user_input_file
echo -n "enter line to add : "
read user_input_text
echo -n "enter line position : "
read user_input_line
In order to add line at the desired position you can "play" with head and tail
head -n $[$user_input_line - 1] $user_input_file > $new_file
echo $user_input_text >> $new_file
tail -n +$user_input_line $user_input_file >> $new_file
Requiring interactive input is horrible for automation. Make a command which accepts a message and a list of files to append to as command-line arguments instead.
#!/bin/sh
msg="$1"
shift
echo "$msg" | tee -a "$#"
Usage:
scriptname "today is a nice day" file1 file2 file3
The benefits for interactive use are obvious -- you get to use your shell's history mechanism and filename completion (usually bound to tab) but also it's much easier to build more complicated scripts on top of this one further on.
The design to put the message in the first command-line argument is baffling to newcomers, but allows for a very simple overall design where "the other arguments" (zero or more) are the files you want to manipulate. See how grep has this design, and sed, and many many other standard Unix commands.
You can use read statement to prompt for input,
read does make your script generic, but if you wish to automate it then you have to have an accompanying expect script to provide inputs to the read statement.
Instead you can take in arguments to the script which helps you in automation.. No prompting...
#!/usr/bin/env bash
[[ $# -ne 2 ]] && echo "print usage here" && exit 1
file=$1 && shift
con=$1
for i in `ls $file`
do
echo $con >> $i
done
To use:
./script.sh "<filename>" "<content>"
The quotes are important for the content so that the spaces in the content are considered to be part of it. For filenames use quotes so that the shell does not expand them before calling the script.
Example: ./script.sh "file*" "samdhaskdnf asdfjhasdf"
In a bash shell script how does one append read data to a csv file?
For example:
#!/bin/bash
echo "Enter name:"
read name
exit 0
If I want $name put into a .csv file from this script, how can this be done?
Maybe I'm missing something, but it sounds like all you need is
echo ${name} >> file.csv
The echo statement will send the value of name to standard output, and the >> will append the standard output to the end of file.csv.
What I have to to is edit a script given to me that will check if the user has write permission for a file named journal-file in the user's home directory. The script should take appropriate actions if journal-file exists and the user does not have write permission to the file.
Here is what I have written so far:
if [ -w $HOME/journal-file ]
then
file=$HOME/journal-file
date >> file
echo -n "Enter name of person or group: "
read name
echo "$name" >> $file
echo >> $file
cat >> $file
echo "--------------------------------" >> $file
echo >> $file
exit 1
else
echo "You do not have write permission."
exit 1
fi
When I run the script it prompt me to input the name of the person/group, but after I press enter nothing happens. It just sits there allowing me to continue inputting stuff and doesn't continue past that part. Why is it doing this?
The statement:
cat >>$file
will read from standard input and write to the file. That means it will wait until you indicate end of file with something like CTRL-D. It's really no different from just typing cat at a command line and seeing that nothing happens until you enter something and it waits until you indicate end of file.
If you're trying to append another file to the output file, you need to specify its name, such as cat $HOME/myfile.txt >>$file.
If you're trying to get a blank line in there, use echo rather than cat, such as echo >>$file.
You also have a couple of other problems, the first being:
date >> file
since that will try to create a file called file (in your working directory). Use $file instead.
The second is the exit code of 1 in the case where what you're trying to do has succeeded. That may not be a problem now but someone using this at a later date may wonder why it seems to indicate failure always.
To be honest, I'm not really a big fan of the if ... then return else ... construct. I prefer fail-fast with less indentation and better grouping of output redirection, such as:
file=${HOME}/journal-file
if [[ ! -w ${file} ]] ; then
echo "You do not have write permission."
exit 1
fi
echo -n "Enter name of person or group: "
read name
(
date
echo "$name"
echo
echo "--------------------------------"
echo
) >>${file}
I believe that's far more readable and maintainable.
It's this line
cat >> $file
cat is concatenating input from standard input (ie whatever you type) to $file
I think the part
cat >> $file
copies everything from stdin to the file. Maybe if you hid Ctrl+D (end of file) the script can continue.
1) You better check first whether the file exists or not:
[[ -e $HOME/journal-file ]] || \
{ echo "$HOME/journal-file does not exist"; exit 1 }
2) You gotta change "cat >> $file" for whatever you want to do with the file. This is the command that is blocking the execution of the script.
I'm writing a shell script that asks for a value and depending on the valued entered returns a value. Imagine that it's called "reve" and contains something like
read fname
rev << EOF
$fname
EOF
Then if I have a file that is called "file.txt" and I do
vi `./reve`
Then waits for user input. If I type "txt.elif" vi opens "file.txt". Correct until now. But the problem is when the script is something like the following
echo "Enter inverted file name"
read fname
rev << EOF
$fname
EOF
Then it tries to open a file called "Enter inverted file name".
Is it possible to ask for the value with the text and after that use the returned value only?
Thanks in advance.
If you really need it to be interactive, then you could print the message on stderr instead.
echo "Enter inverted file name" > /dev/stderr
read fname
rev << EOF
$fname
EOF
Unless you're using a really old shell, read should have a -p option to supply a prompt. It automatically sends the prompt to stderr instead of stdout, and skips the linefeed (so the response is on the same line as the prompt):
read -p "Enter inverted file name: " fname
rev << EOF
$fname
EOF
Force writing to, and reading from, the terminal using /dev/tty.
In your example this will be:
echo -e "Enter inverted file name: \c" > /dev/tty
read fname < /dev/tty
rev << EOF
$fname
EOF
I used echo -e ... \c so no newline is printed and your input is entered on the same line.
I need to configure a server with a few files and I want to do it programmatically.
I need to create files say /home/a.config, /var/spool/b.config, /etc/c.config
Files above have some contents (multi lines).
I want to create ONE shell script which can create all three file with multiple lines (around 10).
I would like to know the how can I use CAT command to do that. (inside shell script).
I am looking something like this
echo " going to create /home/a.config"
cat "HOW CAN I HAVE MULTIPLE LINES HERE?? " > /home/a.config
thanks
You can use a here document:
cat <<EOF >filename
first line
second line
third line
EOF
You can place several of these in the same script.
file="/tmp/test.txt"
echo "Adding first line" > $file
echo "Adding first line replaced" > $file
echo "Appending second line " >> $file
echo "Appending third line" >> $file
cat $file
> to add/replace the content ( here actual content got replaced by the 2nd line)
>> to append
Result
Adding first line replaced
Appending second line
Appending third line
Like so:
#!/bin/bash
var="your text"
echo "simply put,
just so: $var" > a.config
For further info, see Input/Output part of abs.
Hope, this helps.
If you've got variables like $1 or $HOMEDIR in your text then these normally get evaluated and substituted with actual values. If you want to prevent these from getting substituted then you need to quote the opening limit string (EOF in example below) with single quote 'EOF', double quote "EOF" or precede it with backslash \EOF
Closing limit string stays as is. EOF
This is especially useful if you are writing shell scripts to a file.
cat << 'EOF' >/etc/rc.d/init.d/startup
case $1 in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
pid=$(tomcat_pid)
if [ -n "$pid" ]
then
echo "Tomcat is running with pid: $pid"
else
echo "Tomcat is not running"
fi
;;
esac
EOF
Refer Example 19.7 Parameter Substitution Turned off in Here Documents
>\#!/bin/bash
>
>var="your text" <br>
>echo "simply put, <br>
>just so: $var" > a.config
Note that you also need to escape out certain characters to avoid them interfering with what you're trying to do, for example $ ` and " will all break such a statement unless preceded with a backslash, i.e. \` \$ or \"
so if we define the following:
var="100"
the following would not behave as expected:
echo "simply put,
just "lend" me US$ $var" > a.config
but the following would work correctly:
echo "simply put,
just \"lend\" me US\$ $var" > a.config