1

Sorry for asking such a simple question, but reading about this issue on the internet has proven fruitless. I'm trying to better understand the grave/backtick operator and I've been doing okay so far except on one occasion.

Suppose I have a bash script and a variable in it, like so:

var=`ls -al | grep '^...x'

Now, the script requires the user to enter something and based on what that something is, it outputs a result. So, without boring you with the full script, I want to boil it down to one question. If the user inputs "-t" as an argument, the script needs to print all the .txt files that can be executed by the user, i.e, something like:

$var | grep '\.txt$'

Now, the problem arises when I try to reassign the value of var. I tried doing:

var=`$var | grep '\.txt$'`

but this doesn't work. I am not sure what I'm missing here, what is the proper way to deal with this?

Lahsi
  • 21

2 Answers2

1

You should try moving away from the back tick operators for executing commands. Not as portable as using something along the lines of the following:

$ my_var=$(ls -la | grep '^...x')

In regards to your problem, try

$ var=$(echo $var | grep '\.txt$')
PersianGulf
  • 10,850
jas-
  • 868
0

The stuff inside the backticks (it's called command substitution, by the way) is a command to be executed. When you write

$var | grep '\.txt$'

this executes the value of var as a command. That's not what you want: you want to pass the value as input to the grep command. That's basically

echo "$var" | grep '\.txt$'

so the assignment would be

var=`echo "$var" | grep '\.txt$'`

I recommend using the dollar-parenthesis syntax instead of the backticks, because the quoting rules are easier to understand, especially with nested substitutions: a command substitution started with $( extends to the matching ).

var="$(echo "$var" | grep '\.txt$')"

Note the double quotes around $var. The syntax $var only means “the value of var” inside double quotes; outside double quotes, it's more complicated. See Why does my shell script choke on whitespace or other special characters? for more information.

Beware that parsing the output of ls is usually a bad idea. It mangles some file names and is rarely the simplest way. If you want to list only .txt files, simply use the wildcard pattern *.txt (this excludes dot files, unlike ls -al; to include them, add the pattern .*.txt). If you want to consider only the ones that are executable, a robust way is to process them in a loop:

for x in *.txt; do
  if [ -x "$x" ]; then
    … do stuff
  fi
done