In bash, I know that it is possible to write a for
loop in which some loop control variable i
iterates over specified integers. For example, I can write a bash shell script that prints the integers between 1 and 10:
#!/bin/bash
for i in {1..10}
do
echo $i
done
Is it possible to instead iterate over a loop control variable that is a string, if I provide a list of strings? For example, suppose that I have a string fname
that represents a file name. I want to call a set of commands for each file name. For example, I might want to print the contents of fname
using a command like this:
#!/bin/bash
for fname in {"a.txt", "b.txt", "c.txt"}
do
echo $fname
done
In other words, on the first iteration, fname
should have the value fname="a.txt"
, while on the second iteration, fname
should have the value fname="b.txt"
, and so on. Unfortunately, it seems that the above syntax is not quite correct. I would like to obtain the output:
a.txt
b.txt
c.txt
but when I try the above code, I obtain this output:
{a.txt,
b.txt,
c.txt}
Can you please help me determine the correct syntax, so that I can iteratively change the value/contents of the variable fname
? Thank you for your time.
3 Answers 3
The correct syntax is as follows:
#!/bin/bash
for fname in a.txt b.txt c.txt
do
echo $fname
done
-
9Also, assuming an array of names
fnames=( a.txt b.txt c.txt )
you can use the syntaxfor f in ${fnames[@]}; do echo $f; done
.user13742– user137422012年09月08日 19:12:21 +00:00Commented Sep 8, 2012 at 19:12 -
1Is it true that
for fname in a.txt b.txt c.txt
andfor fname in "a.txt" "b.txt" "c.txt"
yield identical results?Andrew– Andrew2012年09月08日 19:39:12 +00:00Commented Sep 8, 2012 at 19:39 -
Andrew, yes it is true. They will yield identical resultsAli Gangji– Ali Gangji2012年09月08日 20:29:19 +00:00Commented Sep 8, 2012 at 20:29
-
1Of course you should use
for f in "${fnames[@]}"; do echo $f; done
(with quotes around${fnames[@]}
) if thefnames
values might contain whitespace. And you should use"$f"
, especially if you're doing anything more sophisticated thanecho
(e.g.,cat
orcp
). (And even if you're only doingecho
, you should useprintf
instead.)Scott - Слава Україні– Scott - Слава Україні2016年04月23日 21:02:32 +00:00Commented Apr 23, 2016 at 21:02 -
I think @user13742 should be also noted in the answer.Fallenreaper– Fallenreaper2018年01月13日 04:53:12 +00:00Commented Jan 13, 2018 at 4:53
Seems to me you should just do...
printf %s.txt\\n a b c
-
I like this even though the OP likely had something in mind to do other than echo before he was done.Elder Geek– Elder Geek2016年02月04日 18:03:04 +00:00Commented Feb 4, 2016 at 18:03
As noted by user13742 in the comments, we can make use of arrays in bash
and ksh
:
#!/usr/bin/env bash
files_list=( "a.txt" "b.txt" "c and space.txt" )
for i in "${files_list[@]}"
do
echo "$i"
# do something else here,maybe
done
And works as so:
$ ./iterate_files_array.sh
a.txt
b.txt
c and space.txt
However, some shells such as dash
( /bin/sh
on Ubuntu ) don't support arrays. In such case we could resort to using here-document structure: <<
#!/bin/sh
while IFS= read -r line
do
echo "$line"
done << EOL
one.txt
two.txt
with space.txt
EOL
{}
, you don't need anything to loop over a (space-delimited) list{}
and the,
s. The alternative is to remove the spaces. So either"a.txt" "b.txt" "c.txt"
or{"a.txt","b.txt","c.txt"}
. But I prefer{a..c}.txt
instead.