I've created a shell script but I don't know how to do a loop that prints the number of lines in every file you pass to the script as argument. So that the output would be something like this:
2 lines in hello.sh
33 lines in /var/log/syslog
Assuming a POSIX shell, you want a for loop here, looping over "$@" which contains the command line arguments:
for filename in "$@"; do
lines=$(wc -l < "$filename")
printf '%u lines in %s\n' "$lines" "$filename"
done
Using all the quotes is quite important. It allows you to pass filenames that contain spaces and other characters.
./my_script.sh /var/log/syslog "$HOME/My Dir with Spaces/a file with spaces.txt"
"$@" is the default target for for, so for filename; do is sufficient.
In general, to loop over the command line argument in a script or shell function, you may do
for thing do
commands using "$thing"
done
or
for thing in "$@"; do
commands using "$thing"
done
In this case, assuming filenames given on the command line do not contain literal newlines, there's no need to do an explicit shell loop for this:
wc -l -- "$@" | sed -E '$d;s/^[[:blank:]]*([[:digit:]]*)[[:blank:]]*(.*)/\1 lines in \2/'
This would take all the command line arguments and run wc -l on them all.
The output is parsed by sed which discards the last line containing the total number of lines in the given files (using $d). The rest of the output from wc -l is transformed into the output that you want by capturing the number of lines and the filename and then inserting the string lines in in-between.
Running the script with my own .vimrc, .profile and .mailrc files will return
8 lines in .vimrc
8 lines in .profile
4 lines in .mailrc
Notice that wc -l -- "$@" will create output like
8 .vimrc
8 .profile
4 .mailrc
20 total
which may actually be enough for what you want, without the need for sed.
wc implementation (POSIX only guarantees there will be at least one blank).
wc -l unless one knows exactly how many blanks it uses as the separator. I've changed it so that it eats up all blanks, assuming the output will only be used for presentation.
#!/bin/bash
for file in "${@}"; do
wc -l -- "${file}"
done
#!/bin/bash Program that will execute this script.
${@} Positional arguments. Arguments that you give to the script through command line.
file Variable that will iterate over the arguments given in ${@}.
wc -l -- "${file}" External command that will print the number of lines in ${file} (except when ${file} is - in which case it will print the number of lines on its standard input).
Alternative using while and shift
while [ $# -gt 0 ] ; do
printf '%u lines in %s\n' $(wc -l < "$1") "$1"
shift
done
wc -l "$@"?