1. Introduction
When writing a Bash script, we may want to process the content of other files passed as an argument to the script.
In this tutorial, we’ll see how to use different methods to pass arguments from a file to a Bash script. Initially, we’ll start with the redirection operators. Then, we’ll look at the command-line method to pass the file content to the Bash script. Lastly, we’ll discuss the export method and a plain bash function to process arguments from a file.
2. Pass Arguments Using Redirection Operator
The first method for passing arguments from a file to a Bash script is to use redirection. In particular, the input redirection operator (<) redirects the contents of the file to the standard input of the Bash script. This way, we can extract the arguments from a file using the read command.
2.1. Simple Arguments
For example, let’s use cat to view the contents of our sample text file args.txt:
$ cat args.txt
foo
bar
Next, we have our Bash script myScript.sh:
$ cat myScript.sh
#!/bin/bash
while read arg; do
echo "Argument: $arg"
done
Here, we use a while loop to get each line of the input as arg and echo that with a prefix.
Now, we can direct the contents of args.txt to myScript.sh using the input redirection operator:
$ ./myScript.sh < args.txt
Once we run the script, we can see each line as a separate usable argument:
Argument: foo
Argument: bar
Of course, we can assign different lines to different script variables based on criteria.
2.2. Complex Arguments
Now, let’s suppose there’s a file called students.txt with student data in two columns:
Name Grade
Sam 70
Smith 80
Alan 40
Tom 60
Shawn 90
We can process this type of data by passing it as an argument to a Bash script. For instance, if we want to calculate the average grade, we again pass the filename using the input redirection operator, and then use the read and cut commands to process the text with a script:
$ cat process_grades.sh
#!/bin/bash
sum=0
count=0
while read line; do
name=$(echo $line | cut -d ' ' -f 1)
grade=$(echo $line | cut -d ' ' -f 2)
sum=$((sum + grade))
count=$((count + 1))
done
avg=$(echo "scale=2; $sum / $count" | bc)
echo "Average grade: $avg"
To elaborate, we’ve used a while loop to read the content of the file. Since the data is stored in two columns, we’ve split the column data into two local variables using the cut command for each line: name and grade. Next, we used the grade variable to calculate the sum of the grades.
In addition, we’re also incrementing the count variable to keep track of the number of grades we’ve processed in the loop. After that, the script calculates the average of the total grade. Notably, we’ve used the bc command for floating point calculation.
Finally, we can execute process_grades.sh with the students.txt contents redirected to it:
$ ./process_grades.sh < students.txt
Average grade: 56.66
From the output, we can see the average grade of all students based on the file data.
3. Use Command-Line Argument Variables
Another method to pass arguments from a file is to use the command-line arguments mechanism. To elaborate, we pass the filename as an argument and then read the contents of the file inside the Bash script.
Let’s take our earlier args.txt file as an example:
$ cat args.txt
foo
bar
Our script has a couple of additions this time:
$ cat myScript.sh
#!/bin/bash
file="$1"
while read arg; do
echo "Argument: $arg"
done < "$file"
When we pass arguments to a Bash script through the command line, the first argument is usually indicated as $1, the second argument as $2, and so on. On the other hand, $0 indicates the filename.
So, to actually read the file itself, we first assign the filename argument to a local variable. Then, *we use the read command with a loop to read the contents of that file as redirected via <, but this time within the script itself*.
Finally, we execute the script using the filename as the command-line argument to get its contents:
$ ./myScript.sh args.txt
Argument: foo
Argument: bar
Like before, we get each line of the file.
4. The export Command
Another possible method to pass arguments from a file to a Bash script is to use environment variables. To elaborate, this method involves exporting the contents of the file as an environment variable before accessing the latter inside the Bash script. For this method, we use the export command.
For instance, we have a file called args.txt:
$ cat args.txt
This is line 1
This is line 2
To export the contents of this text file into a variable, we’ll use the export command:
$ export ARGS="$(cat args.txt)"
Next, to access the variable inside the Bash script, we’ll simply assign it to a local bash variable and iterate using a loop:
$ cat myScript.sh
#!/bin/bash
args="$ARGS"
for arg in $args; do
echo "Argument: $arg"
done
After that, since we already have the ARGS variable, we’ll run myScript.sh without any arguments or redirection:
$ ./myScript.sh
Argument: This is line 1
Argument: This is line 2
If we have data in columns in the .txt file, we can modify the Bash script to parse the columns:
$ cat myScript.sh
#!/bin/bash
data="$ARGS"
for line in $(echo "$data" | tr ',' ' '); do
echo line
done
The code given above works for columns separated by a comma.
It’s crucial to understand that we must use the environment variables with caution, as they are visible to the current shell and all its child processes. In addition, if the file size is much larger than what our shell can normally handle, this can lead to instability or even crashes.
5. Pass Arguments Using Command Substitution
Command substitution is a bash feature that allows us to substitute the output of a command within a command line. We can also use this feature to pass arguments from a file to a Bash script.
Let’s use our earlier args.txt example:
$ cat args.txt
This is line 1
This is line 2
Next, we have our bashscript myScript.sh:
$ cat myScript.sh
#!/bin/bash
for arg in "$@"; do
echo "Processing argument: $arg"
done
In this example, we’ve used a loop to iterate over the command-line arguments passed to the script using $@. The script processes each argument passed from the file.
After that, we’ll run the script and supply the output of cat args.txt via command substitution:
$ ./myScript.sh "$(cat args.txt)"
Processing argument: This is line 1
Processing argument: This is line 2
Of course, using the command substitution can potentially leverage shell command injection vulnerabilities. This usually happens when the file passed as an argument contains symbols or special characters that are executed by the shell. For that reason, it’s important that we use it carefully and properly format the file before passing it as an argument to the Bash script.
In addition, it can also cause the shell to spawn new processes or crash if we pass a large number of command-line arguments. Passing a large number of arguments may cause a buffer overflow. Therefore, we should properly chunk the arguments before processing.
6. Conclusion
In this article, we’ve seen how to use different methods to pass arguments from a file to a Bash script.
To begin with, we discussed the input redirection operator and passing files as command-line arguments. We also saw how to use the export command to process file contents inside the Bash script.
Then, we looked at command substitution as a possible way to get file contents to the command line. Lastly, we learned that it’s crucial to be cautious when using both the export command and command substitution.