I need to get multiple txt files strings by entering the names in a single string. Example ./3.sh 3.txt 2.txt.
Current script reads only the first typed txt file.
Hello, welcome to the forums.
First thoughts, the script is all over the place. There's an array declaration that's never used. And there's over-(ab?)use of exec.
From what I understand of your requirement, you want to just print the contents of the files that you supply to the script as arguments. Is that correct? Something as simple as below would suffice:
#! /bin/bash
for file in $@
do
echo "******************* $file ********************"
cat $file
done
Or simply on the command line:
cat file1 file2 file3
But where does this fit exactly? What's the real requirement? Is this a homework question just to display the use of exec?
HTH.
Hello, thank You for Your response. This is a homework question and i must use exec function. As you can see, if I type ./3.sh 2.txt 3.txt the script will only read 2.txt but i need it to read multiple txt files.
This is "Cargo Cult" code. You put in some stuff off the internet, but you don't actually see why it is there.
(a) declare -a FILES : the array is neither populated or used. Why do you declare it?
(b) exec < $1 : attaches stdin to the file names as arg 1. But you never read stdin, you explicitly read $1 itself in the while-loop. So the exec has no purpose.
(c) You only reference $1 (i.e. file named in arg1). Why would you expect it ever to look at later arguments? You need to loop over the args in an outer loop: your current while only deals with a single file.
(d) exec 10<&0 and exec 0<&10 10<&- essentially park stdin onto a spare file descriptor, so you can exec stdin as a file, and then reinstate it.
Take small steps. I would suggest you start over by populating FILES from the args, and using declare -p FILES to prove it worked.
Then add a loop that iterates over the elements of FILES and shows each file that can be read.
Finally, add in your read loop to process each file in turn.
What you probably are expected to do is: to park stdin on fd10 once; then exec stdin to each filename in FILES in turn, and list the contents, and close that stdin (with your loop readings stdin, not the arg of the filename); then finally reinstate the initial stdin.
This is a bizarre way to do things: exec has some good use cases, but this is not one of them. However, what you need to do is to keep track (on paper) of what each fd is connected to at each step.
My sincere apologies. I tend to forget how unfamiliar everything is for the first few months. Also, it appears your teacher may not be at the top of their profession, which will not make things easier for you.
Nevertheless, there are a few principles that may help, if you care to apply them.
(a) Solve one small part of the problem at a time, before moving on to the next.
(b) Avoid putting statements in your code unless you can explain to yourself exactly why you need them.
(c) Never assume a variable is correct until you have output it (declare -p shows you the truth better than print or echo).
I can recommend two resources.
shellcheck.net validates script syntax (which can baffle the best of us), and can be used in a browser or downloaded to your own system.
Bash Reference Manual is a full reference guide, with examples. It is huge, but has both index and contents.
A small hint to get you started. This statement populates your FILES array with all of your script arguments (the filenames), and then shows the array.
declare -a FILES=( "${@}" )
declare -p FILES
And this loops through the array, setting file to each arg in turn.
for file in "${FILES[@]}"; do
...
done
