0

I am sure this has been answered before, but I cannot find the solution.

for i in `ls | grep ^t`; do echo $i; done

This gives me the expected results (the files and directories starting with t). If I want to use a shell variable in the for loop (with the pipe), how do I do this? This was my start but it does not work.

z="ls | grep ^t"
for i in `$z` ; do echo $i; done

EDIT: I agree this example was not wisely chosen, but what I basically need ishow to use a variable (here $z) in the for loop (for i in $z) which has at least one pipe.

I try to state my question more clearly: How do I need to define my variable (if I want to loop over the output of a command with one or more pipes) and how is the call for the for loop?

6
  • you should write z=`ls | grep ^t` Commented Mar 17, 2016 at 15:16
  • 1
    @PatrickTrentin It's syntactically correct, but you shouldn't use it. Commented Mar 17, 2016 at 15:28
  • @chepner fair enough; eta: never-mind, I looked it on my own. (: Commented Mar 17, 2016 at 15:34
  • @chepner I answered z=`ls | grep ^t` for i in "$z"; do echo $i; done and z="$(ls | grep ^t)"; for i in "$z"; do echo $i; done and I got -3 do you know why? Please give me some advice. Commented Mar 17, 2016 at 15:46
  • 1
    @terces907 Because parsing ls is bad. Commented Mar 17, 2016 at 15:51

2 Answers 2

4

To loop through all files starting with t, you should use glob expansion instead of parsing ls output:

$ ls t*
tf  tfile
$ ls
abcd  tf  tfile
$ for i in t*; do echo "$i"; done
tf
tfile
$

Your approach will break in a number of cases, the simplest being when file names contain spaces. There is no need to use any external tool here; t* expands to all files starting with t.

As for your question, you use ls | grep ^t

And another good practice is to use subshell instead of backticks which are more readable and can be nested, use this: $(ls | grep ^t)

Sign up to request clarification or add additional context in comments.

1 Comment

I only read the first part of your answer, which was why I posted my own. Your advice to use t* is the best idea - you should move that to the top of your answer then I'll delete mine.
0

You don't use a variable for this. You don't put commands in strings. See Bash FAQ 050 for discussion about why.

You shouldn't be using a for loop to read data line-by-line anyway. See Bash FAR 001 for better ways to do that.

Specifically (though really read that page):

while IFS= read -r line; do
  printf '%s\n' "$line"
done < <(some command)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.